]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_spf.c
tests: Enhance error msgs for static route auto.
[mirror_frr.git] / ospf6d / ospf6_spf.c
1 /*
2 * Copyright (C) 2003 Yasuhiro Ohara
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /* Shortest Path First calculation for OSPFv3 */
22
23 #include <zebra.h>
24
25 #include "log.h"
26 #include "memory.h"
27 #include "command.h"
28 #include "vty.h"
29 #include "prefix.h"
30 #include "linklist.h"
31 #include "thread.h"
32 #include "lib_errors.h"
33
34 #include "ospf6_lsa.h"
35 #include "ospf6_lsdb.h"
36 #include "ospf6_route.h"
37 #include "ospf6_area.h"
38 #include "ospf6_proto.h"
39 #include "ospf6_abr.h"
40 #include "ospf6_asbr.h"
41 #include "ospf6_spf.h"
42 #include "ospf6_intra.h"
43 #include "ospf6_interface.h"
44 #include "ospf6d.h"
45 #include "ospf6_abr.h"
46 #include "ospf6_nssa.h"
47 #include "ospf6_zebra.h"
48
49 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex");
50
51 unsigned char conf_debug_ospf6_spf = 0;
52
53 static void ospf6_spf_copy_nexthops_to_route(struct ospf6_route *rt,
54 struct ospf6_vertex *v)
55 {
56 if (rt && v)
57 ospf6_copy_nexthops(rt->nh_list, v->nh_list);
58 }
59
60 static void ospf6_spf_merge_nexthops_to_route(struct ospf6_route *rt,
61 struct ospf6_vertex *v)
62 {
63 if (rt && v)
64 ospf6_merge_nexthops(rt->nh_list, v->nh_list);
65 }
66
67 static unsigned int ospf6_spf_get_ifindex_from_nh(struct ospf6_vertex *v)
68 {
69 struct ospf6_nexthop *nh;
70 struct listnode *node;
71
72 if (v) {
73 node = listhead(v->nh_list);
74 if (node) {
75 nh = listgetdata(node);
76 if (nh)
77 return (nh->ifindex);
78 }
79 }
80 return 0;
81 }
82
83 static int ospf6_vertex_cmp(const struct ospf6_vertex *va,
84 const struct ospf6_vertex *vb)
85 {
86 /* ascending order */
87 if (va->cost != vb->cost)
88 return (va->cost - vb->cost);
89 if (va->hops != vb->hops)
90 return (va->hops - vb->hops);
91 return 0;
92 }
93 DECLARE_SKIPLIST_NONUNIQ(vertex_pqueue, struct ospf6_vertex, pqi,
94 ospf6_vertex_cmp);
95
96 static int ospf6_vertex_id_cmp(void *a, void *b)
97 {
98 struct ospf6_vertex *va = (struct ospf6_vertex *)a;
99 struct ospf6_vertex *vb = (struct ospf6_vertex *)b;
100 int ret = 0;
101
102 ret = ntohl(ospf6_linkstate_prefix_adv_router(&va->vertex_id))
103 - ntohl(ospf6_linkstate_prefix_adv_router(&vb->vertex_id));
104 if (ret)
105 return ret;
106
107 ret = ntohl(ospf6_linkstate_prefix_id(&va->vertex_id))
108 - ntohl(ospf6_linkstate_prefix_id(&vb->vertex_id));
109 return ret;
110 }
111
112 static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
113 {
114 struct ospf6_vertex *v;
115
116 v = XMALLOC(MTYPE_OSPF6_VERTEX, sizeof(struct ospf6_vertex));
117
118 /* type */
119 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
120 v->type = OSPF6_VERTEX_TYPE_ROUTER;
121 /* Router LSA use Link ID 0 as base in vertex_id */
122 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0),
123 &v->vertex_id);
124 } else if (ntohs(lsa->header->type) == OSPF6_LSTYPE_NETWORK) {
125 v->type = OSPF6_VERTEX_TYPE_NETWORK;
126 /* vertex_id */
127 ospf6_linkstate_prefix(lsa->header->adv_router, lsa->header->id,
128 &v->vertex_id);
129 } else
130 assert(0);
131
132 /* name */
133 ospf6_linkstate_prefix2str(&v->vertex_id, v->name, sizeof(v->name));
134
135 if (IS_OSPF6_DEBUG_SPF(PROCESS))
136 zlog_debug("%s: Creating vertex %s of type %s (0x%04hx) lsa %s",
137 __func__, v->name,
138 ((ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER)
139 ? "Router"
140 : "N/W"),
141 ntohs(lsa->header->type), lsa->name);
142
143
144 /* Associated LSA */
145 v->lsa = lsa;
146
147 /* capability bits + options */
148 v->capability = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header));
149 v->options[0] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 1);
150 v->options[1] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 2);
151 v->options[2] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
152
153 v->nh_list = list_new();
154 v->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
155 v->nh_list->del = (void (*)(void *))ospf6_nexthop_delete;
156
157 v->parent = NULL;
158 v->child_list = list_new();
159 v->child_list->cmp = ospf6_vertex_id_cmp;
160
161 return v;
162 }
163
164 static void ospf6_vertex_delete(struct ospf6_vertex *v)
165 {
166 list_delete(&v->nh_list);
167 list_delete(&v->child_list);
168 XFREE(MTYPE_OSPF6_VERTEX, v);
169 }
170
171 static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
172 struct ospf6_vertex *v)
173 {
174 struct ospf6_lsa *lsa = NULL;
175 uint16_t type = 0;
176 uint32_t id = 0, adv_router = 0;
177
178 if (VERTEX_IS_TYPE(NETWORK, v)) {
179 type = htons(OSPF6_LSTYPE_ROUTER);
180 id = htonl(0);
181 adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
182 } else {
183 if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
184 type = htons(OSPF6_LSTYPE_ROUTER);
185 id = htonl(0);
186 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
187 } else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
188 type = htons(OSPF6_LSTYPE_NETWORK);
189 id = htonl(ROUTER_LSDESC_GET_NBR_IFID(lsdesc));
190 adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
191 }
192 }
193
194 if (type == htons(OSPF6_LSTYPE_NETWORK))
195 lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb);
196 else
197 lsa = ospf6_create_single_router_lsa(v->area, v->area->lsdb,
198 adv_router);
199 if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
200 char ibuf[16], abuf[16];
201 inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
202 inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
203 if (lsa)
204 zlog_debug(" Link to: %s len %u, V %s", lsa->name,
205 ntohs(lsa->header->length), v->name);
206 else
207 zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s",
208 ospf6_lstype_name(type), ibuf, abuf,
209 v->name);
210 }
211
212 return lsa;
213 }
214
215 static char *ospf6_lsdesc_backlink(struct ospf6_lsa *lsa, caddr_t lsdesc,
216 struct ospf6_vertex *v)
217 {
218 caddr_t backlink, found = NULL;
219 int size;
220
221 size = (OSPF6_LSA_IS_TYPE(ROUTER, lsa)
222 ? sizeof(struct ospf6_router_lsdesc)
223 : sizeof(struct ospf6_network_lsdesc));
224 for (backlink = OSPF6_LSA_HEADER_END(lsa->header) + 4;
225 backlink + size <= OSPF6_LSA_END(lsa->header); backlink += size) {
226 assert(!(OSPF6_LSA_IS_TYPE(NETWORK, lsa)
227 && VERTEX_IS_TYPE(NETWORK, v)));
228
229 if (OSPF6_LSA_IS_TYPE(NETWORK, lsa)) {
230 if (NETWORK_LSDESC_GET_NBR_ROUTERID(backlink)
231 == v->lsa->header->adv_router)
232 found = backlink;
233 } else if (VERTEX_IS_TYPE(NETWORK, v)) {
234 if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, backlink)
235 && ROUTER_LSDESC_GET_NBR_ROUTERID(backlink)
236 == v->lsa->header->adv_router
237 && ROUTER_LSDESC_GET_NBR_IFID(backlink)
238 == ntohl(v->lsa->header->id))
239 found = backlink;
240 } else {
241 assert(OSPF6_LSA_IS_TYPE(ROUTER, lsa)
242 && VERTEX_IS_TYPE(ROUTER, v));
243
244 if (!ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, backlink)
245 || !ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc))
246 continue;
247
248 if (ROUTER_LSDESC_GET_NBR_IFID(backlink)
249 != ROUTER_LSDESC_GET_IFID(lsdesc)
250 || ROUTER_LSDESC_GET_NBR_IFID(lsdesc)
251 != ROUTER_LSDESC_GET_IFID(backlink))
252 continue;
253 if (ROUTER_LSDESC_GET_NBR_ROUTERID(backlink)
254 != v->lsa->header->adv_router
255 || ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc)
256 != lsa->header->adv_router)
257 continue;
258 found = backlink;
259 }
260 }
261
262 if (IS_OSPF6_DEBUG_SPF(PROCESS))
263 zlog_debug("Vertex %s Lsa %s Backlink %s", v->name, lsa->name,
264 (found ? "OK" : "FAIL"));
265
266 return found;
267 }
268
269 static void ospf6_nexthop_calc(struct ospf6_vertex *w, struct ospf6_vertex *v,
270 caddr_t lsdesc, struct ospf6 *ospf6)
271 {
272 int i;
273 ifindex_t ifindex;
274 struct ospf6_interface *oi;
275 uint16_t type;
276 uint32_t adv_router;
277 struct ospf6_lsa *lsa;
278 struct ospf6_link_lsa *link_lsa;
279 char buf[64];
280
281 assert(VERTEX_IS_TYPE(ROUTER, w));
282 ifindex = (VERTEX_IS_TYPE(NETWORK, v) ? ospf6_spf_get_ifindex_from_nh(v)
283 : ROUTER_LSDESC_GET_IFID(lsdesc));
284 if (ifindex == 0) {
285 flog_err(EC_LIB_DEVELOPMENT, "No nexthop ifindex at vertex %s",
286 v->name);
287 return;
288 }
289
290 oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id);
291 if (oi == NULL) {
292 zlog_warn("Can't find interface in SPF: ifindex %d", ifindex);
293 return;
294 }
295
296 type = htons(OSPF6_LSTYPE_LINK);
297 adv_router = (VERTEX_IS_TYPE(NETWORK, v)
298 ? NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc)
299 : ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc));
300
301 i = 0;
302 for (ALL_LSDB_TYPED_ADVRTR(oi->lsdb, type, adv_router, lsa)) {
303 if (VERTEX_IS_TYPE(ROUTER, v)
304 && htonl(ROUTER_LSDESC_GET_NBR_IFID(lsdesc))
305 != lsa->header->id)
306 continue;
307
308 link_lsa = (struct ospf6_link_lsa *)OSPF6_LSA_HEADER_END(
309 lsa->header);
310 if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
311 inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
312 sizeof(buf));
313 zlog_debug(" nexthop %s from %s", buf, lsa->name);
314 }
315
316 ospf6_add_nexthop(w->nh_list, ifindex,
317 &link_lsa->linklocal_addr);
318 i++;
319 }
320
321 if (i == 0 && IS_OSPF6_DEBUG_SPF(PROCESS))
322 zlog_debug("No nexthop for %s found", w->name);
323 }
324
325 static int ospf6_spf_install(struct ospf6_vertex *v,
326 struct ospf6_route_table *result_table)
327 {
328 struct ospf6_route *route, *parent_route;
329 struct ospf6_vertex *prev;
330
331 if (IS_OSPF6_DEBUG_SPF(PROCESS))
332 zlog_debug("SPF install %s (lsa %s) hops %d cost %d", v->name,
333 v->lsa->name, v->hops, v->cost);
334
335 route = ospf6_route_lookup(&v->vertex_id, result_table);
336 if (route && route->path.cost < v->cost) {
337 if (IS_OSPF6_DEBUG_SPF(PROCESS))
338 zlog_debug(
339 " already installed with lower cost (%d), ignore",
340 route->path.cost);
341 ospf6_vertex_delete(v);
342 return -1;
343 } else if (route && route->path.cost == v->cost) {
344 if (IS_OSPF6_DEBUG_SPF(PROCESS))
345 zlog_debug(
346 " another path found to route %pFX lsa %s, merge",
347 &route->prefix, v->lsa->name);
348 ospf6_spf_merge_nexthops_to_route(route, v);
349
350 prev = (struct ospf6_vertex *)route->route_option;
351 assert(prev->hops <= v->hops);
352
353 if ((VERTEX_IS_TYPE(ROUTER, v)
354 && route->path.origin.id != v->lsa->header->id)) {
355 if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
356 zlog_debug(
357 "%s: V lsa %s id %u, route id %u are different",
358 __func__, v->lsa->name,
359 ntohl(v->lsa->header->id),
360 ntohl(route->path.origin.id));
361 }
362 return 0;
363 }
364
365 ospf6_vertex_delete(v);
366 return -1;
367 }
368
369 /* There should be no case where candidate being installed (variable
370 "v") is closer than the one in the SPF tree (variable "route").
371 In the case something has gone wrong with the behavior of
372 Priority-Queue. */
373
374 /* the case where the route exists already is handled and returned
375 up to here. */
376 assert(route == NULL);
377
378 route = ospf6_route_create(v->area->ospf6);
379 memcpy(&route->prefix, &v->vertex_id, sizeof(struct prefix));
380 route->type = OSPF6_DEST_TYPE_LINKSTATE;
381 route->path.type = OSPF6_PATH_TYPE_INTRA;
382 route->path.origin.type = v->lsa->header->type;
383 route->path.origin.id = v->lsa->header->id;
384 route->path.origin.adv_router = v->lsa->header->adv_router;
385 route->path.metric_type = 1;
386 route->path.cost = v->cost;
387 route->path.u.cost_e2 = v->hops;
388 route->path.router_bits = v->capability;
389 route->path.options[0] = v->options[0];
390 route->path.options[1] = v->options[1];
391 route->path.options[2] = v->options[2];
392
393 ospf6_spf_copy_nexthops_to_route(route, v);
394
395 /*
396 * The SPF logic implementation does not transfer the multipathing
397 * properties
398 * of a parent to a child node. Thus if there was a 3-way multipath to a
399 * node's parent and a single hop from the parent to the child, the
400 * logic of
401 * creating new vertices and computing next hops prevents there from
402 * being 3
403 * paths to the child node. This is primarily because the resolution of
404 * multipath is done in this routine, not in the main spf loop.
405 *
406 * The following logic addresses that problem by merging the parent's
407 * nexthop
408 * information with the child's, if the parent is not the root of the
409 * tree.
410 * This is based on the assumption that before a node's route is
411 * installed,
412 * its parent's route's nexthops have already been installed.
413 */
414 if (v->parent && v->parent->hops) {
415 parent_route =
416 ospf6_route_lookup(&v->parent->vertex_id, result_table);
417 if (parent_route) {
418 ospf6_route_merge_nexthops(route, parent_route);
419 }
420 }
421
422 if (v->parent)
423 listnode_add_sort(v->parent->child_list, v);
424 route->route_option = v;
425
426 ospf6_route_add(route, result_table);
427 return 0;
428 }
429
430 void ospf6_spf_table_finish(struct ospf6_route_table *result_table)
431 {
432 struct ospf6_route *route, *nroute;
433 struct ospf6_vertex *v;
434 for (route = ospf6_route_head(result_table); route; route = nroute) {
435 nroute = ospf6_route_next(route);
436 v = (struct ospf6_vertex *)route->route_option;
437 ospf6_vertex_delete(v);
438 ospf6_route_remove(route, result_table);
439 }
440 }
441
442 static const char *const ospf6_spf_reason_str[] = {
443 "R+", /* OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED */
444 "R-", /* OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED */
445 "N+", /* OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED */
446 "N-", /* OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED */
447 "L+", /* OSPF6_SPF_FLAGS_NETWORK_LINK_LSA_ADDED */
448 "L-", /* OSPF6_SPF_FLAGS_NETWORK_LINK_LSA_REMOVED */
449 "R*", /* OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED */
450 "N*", /* OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED */
451 "C", /* OSPF6_SPF_FLAGS_CONFIG_CHANGE */
452 "A", /* OSPF6_SPF_FLAGS_ASBR_STATUS_CHANGE */
453 "GR", /* OSPF6_SPF_FLAGS_GR_FINISH */
454 };
455
456 void ospf6_spf_reason_string(uint32_t reason, char *buf, int size)
457 {
458 uint32_t bit;
459 int len = 0;
460
461 if (!buf)
462 return;
463
464 if (!reason) {
465 buf[0] = '\0';
466 return;
467 }
468 for (bit = 0; bit < array_size(ospf6_spf_reason_str); bit++) {
469 if ((reason & (1 << bit)) && (len < size)) {
470 len += snprintf((buf + len), (size - len), "%s%s",
471 (len > 0) ? ", " : "",
472 ospf6_spf_reason_str[bit]);
473 }
474 }
475 }
476
477 /* RFC2328 16.1. Calculating the shortest-path tree for an area */
478 /* RFC2740 3.8.1. Calculating the shortest path tree for an area */
479 void ospf6_spf_calculation(uint32_t router_id,
480 struct ospf6_route_table *result_table,
481 struct ospf6_area *oa)
482 {
483 struct vertex_pqueue_head candidate_list;
484 struct ospf6_vertex *root, *v, *w;
485 int size;
486 caddr_t lsdesc;
487 struct ospf6_lsa *lsa;
488 struct in6_addr address;
489
490 ospf6_spf_table_finish(result_table);
491
492 /* Install the calculating router itself as the root of the SPF tree */
493 /* construct root vertex */
494 lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
495 if (lsa == NULL) {
496 zlog_warn("%s: No router LSA for area %s", __func__, oa->name);
497 return;
498 }
499
500 /* initialize */
501 vertex_pqueue_init(&candidate_list);
502
503 root = ospf6_vertex_create(lsa);
504 root->area = oa;
505 root->cost = 0;
506 root->hops = 0;
507 root->link_id = lsa->header->id;
508 inet_pton(AF_INET6, "::1", &address);
509
510 /* Actually insert root to the candidate-list as the only candidate */
511 vertex_pqueue_add(&candidate_list, root);
512
513 /* Iterate until candidate-list becomes empty */
514 while ((v = vertex_pqueue_pop(&candidate_list))) {
515 /* installing may result in merging or rejecting of the vertex
516 */
517 if (ospf6_spf_install(v, result_table) < 0)
518 continue;
519
520 /* Skip overloaded routers */
521 if ((OSPF6_LSA_IS_TYPE(ROUTER, v->lsa)
522 && ospf6_router_is_stub_router(v->lsa)))
523 continue;
524
525 /* For each LS description in the just-added vertex V's LSA */
526 size = (VERTEX_IS_TYPE(ROUTER, v)
527 ? sizeof(struct ospf6_router_lsdesc)
528 : sizeof(struct ospf6_network_lsdesc));
529 for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
530 lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
531 lsdesc += size) {
532 lsa = ospf6_lsdesc_lsa(lsdesc, v);
533 if (lsa == NULL)
534 continue;
535
536 if (OSPF6_LSA_IS_MAXAGE(lsa))
537 continue;
538
539 if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
540 continue;
541
542 w = ospf6_vertex_create(lsa);
543 w->area = oa;
544 w->parent = v;
545 if (VERTEX_IS_TYPE(ROUTER, v)) {
546 w->cost = v->cost
547 + ROUTER_LSDESC_GET_METRIC(lsdesc);
548 w->hops =
549 v->hops
550 + (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
551 } else {
552 /* NETWORK */
553 w->cost = v->cost;
554 w->hops = v->hops + 1;
555 }
556
557 /* nexthop calculation */
558 if (w->hops == 0)
559 ospf6_add_nexthop(
560 w->nh_list,
561 ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
562 else if (w->hops == 1 && v->hops == 0)
563 ospf6_nexthop_calc(w, v, lsdesc, oa->ospf6);
564 else
565 ospf6_copy_nexthops(w->nh_list, v->nh_list);
566
567
568 /* add new candidate to the candidate_list */
569 if (IS_OSPF6_DEBUG_SPF(PROCESS))
570 zlog_debug(
571 " New candidate: %s hops %d cost %d",
572 w->name, w->hops, w->cost);
573 vertex_pqueue_add(&candidate_list, w);
574 }
575 }
576
577 //vertex_pqueue_fini(&candidate_list);
578
579 ospf6_remove_temp_router_lsa(oa);
580
581 oa->spf_calculation++;
582 }
583
584 static void ospf6_spf_log_database(struct ospf6_area *oa)
585 {
586 char *p, *end, buffer[256];
587 struct listnode *node;
588 struct ospf6_interface *oi;
589
590 p = buffer;
591 end = buffer + sizeof(buffer);
592
593 snprintf(p, end - p, "SPF on DB (#LSAs):");
594 p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer) : end);
595 snprintf(p, end - p, " Area %s: %d", oa->name, oa->lsdb->count);
596 p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer) : end);
597
598 for (ALL_LIST_ELEMENTS_RO(oa->if_list, node, oi)) {
599 snprintf(p, end - p, " I/F %s: %d", oi->interface->name,
600 oi->lsdb->count);
601 p = (buffer + strlen(buffer) < end ? buffer + strlen(buffer)
602 : end);
603 }
604
605 zlog_debug("%s", buffer);
606 }
607
608 static void ospf6_spf_calculation_thread(struct thread *t)
609 {
610 struct ospf6_area *oa;
611 struct ospf6 *ospf6;
612 struct timeval start, end, runtime;
613 struct listnode *node;
614 int areas_processed = 0;
615 char rbuf[32];
616
617 ospf6 = (struct ospf6 *)THREAD_ARG(t);
618
619 /* execute SPF calculation */
620 monotime(&start);
621 ospf6->ts_spf = start;
622
623 if (ospf6_check_and_set_router_abr(ospf6))
624 ospf6_abr_range_reset_cost(ospf6);
625
626 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
627
628 if (oa == ospf6->backbone)
629 continue;
630
631 monotime(&oa->ts_spf);
632 if (IS_OSPF6_DEBUG_SPF(PROCESS))
633 zlog_debug("SPF calculation for Area %s", oa->name);
634 if (IS_OSPF6_DEBUG_SPF(DATABASE))
635 ospf6_spf_log_database(oa);
636
637 ospf6_spf_calculation(ospf6->router_id, oa->spf_table, oa);
638 ospf6_intra_route_calculation(oa);
639 ospf6_intra_brouter_calculation(oa);
640
641 areas_processed++;
642 }
643
644 if (ospf6->backbone) {
645 monotime(&ospf6->backbone->ts_spf);
646 if (IS_OSPF6_DEBUG_SPF(PROCESS))
647 zlog_debug("SPF calculation for Backbone area %s",
648 ospf6->backbone->name);
649 if (IS_OSPF6_DEBUG_SPF(DATABASE))
650 ospf6_spf_log_database(ospf6->backbone);
651
652 ospf6_spf_calculation(ospf6->router_id,
653 ospf6->backbone->spf_table,
654 ospf6->backbone);
655 ospf6_intra_route_calculation(ospf6->backbone);
656 ospf6_intra_brouter_calculation(ospf6->backbone);
657 areas_processed++;
658 }
659
660 /* External LSA calculation */
661 ospf6_ase_calculate_timer_add(ospf6);
662
663 if (ospf6_check_and_set_router_abr(ospf6)) {
664 ospf6_abr_defaults_to_stub(ospf6);
665 ospf6_abr_nssa_type_7_defaults(ospf6);
666 }
667
668 monotime(&end);
669 timersub(&end, &start, &runtime);
670
671 ospf6->ts_spf_duration = runtime;
672
673 ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
674
675 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
676 zlog_debug(
677 "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s",
678 areas_processed, (long long)runtime.tv_sec,
679 (long long)runtime.tv_usec, rbuf);
680
681 ospf6->last_spf_reason = ospf6->spf_reason;
682 ospf6_reset_spf_reason(ospf6);
683 }
684
685 /* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
686 set timer for SPF calc. */
687 void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason)
688 {
689 unsigned long delay, elapsed, ht;
690
691 /* OSPF instance does not exist. */
692 if (ospf6 == NULL)
693 return;
694
695 ospf6_set_spf_reason(ospf6, reason);
696
697 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME)) {
698 char rbuf[32];
699 ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
700 zlog_debug("SPF: calculation timer scheduled (reason %s)",
701 rbuf);
702 }
703
704 /* SPF calculation timer is already scheduled. */
705 if (thread_is_scheduled(ospf6->t_spf_calc)) {
706 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
707 zlog_debug(
708 "SPF: calculation timer is already scheduled: %p",
709 (void *)ospf6->t_spf_calc);
710 return;
711 }
712
713 elapsed = monotime_since(&ospf6->ts_spf, NULL) / 1000LL;
714 ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;
715
716 if (ht > ospf6->spf_max_holdtime)
717 ht = ospf6->spf_max_holdtime;
718
719 /* Get SPF calculation delay time. */
720 if (elapsed < ht) {
721 /* Got an event within the hold time of last SPF. We need to
722 * increase the hold_multiplier, if it's not already at/past
723 * maximum value, and wasn't already increased..
724 */
725 if (ht < ospf6->spf_max_holdtime)
726 ospf6->spf_hold_multiplier++;
727
728 /* always honour the SPF initial delay */
729 if ((ht - elapsed) < ospf6->spf_delay)
730 delay = ospf6->spf_delay;
731 else
732 delay = ht - elapsed;
733 } else {
734 /* Event is past required hold-time of last SPF */
735 delay = ospf6->spf_delay;
736 ospf6->spf_hold_multiplier = 1;
737 }
738
739 if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
740 zlog_debug("SPF: Rescheduling in %ld msec", delay);
741
742 THREAD_OFF(ospf6->t_spf_calc);
743 thread_add_timer_msec(master, ospf6_spf_calculation_thread, ospf6,
744 delay, &ospf6->t_spf_calc);
745 }
746
747 void ospf6_spf_display_subtree(struct vty *vty, const char *prefix, int rest,
748 struct ospf6_vertex *v, json_object *json_obj,
749 bool use_json)
750 {
751 struct listnode *node, *nnode;
752 struct ospf6_vertex *c;
753 char *next_prefix;
754 int len;
755 int restnum;
756 json_object *json_childs = NULL;
757 json_object *json_child = NULL;
758
759 if (use_json) {
760 json_childs = json_object_new_object();
761 json_object_int_add(json_obj, "cost", v->cost);
762 } else {
763 /* "prefix" is the space prefix of the display line */
764 vty_out(vty, "%s+-%s [%d]\n", prefix, v->name, v->cost);
765 }
766
767 len = strlen(prefix) + 4;
768 next_prefix = (char *)malloc(len);
769 if (next_prefix == NULL) {
770 vty_out(vty, "malloc failed\n");
771 return;
772 }
773 snprintf(next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
774
775 restnum = listcount(v->child_list);
776 for (ALL_LIST_ELEMENTS(v->child_list, node, nnode, c)) {
777 if (use_json)
778 json_child = json_object_new_object();
779 else
780 restnum--;
781
782 ospf6_spf_display_subtree(vty, next_prefix, restnum, c,
783 json_child, use_json);
784
785 if (use_json)
786 json_object_object_add(json_childs, c->name,
787 json_child);
788 }
789 if (use_json) {
790 json_object_boolean_add(json_obj, "isLeafNode",
791 !listcount(v->child_list));
792 if (listcount(v->child_list))
793 json_object_object_add(json_obj, "children",
794 json_childs);
795 else
796 json_object_free(json_childs);
797 }
798 free(next_prefix);
799 }
800
801 DEFUN (debug_ospf6_spf_process,
802 debug_ospf6_spf_process_cmd,
803 "debug ospf6 spf process",
804 DEBUG_STR
805 OSPF6_STR
806 "Debug SPF Calculation\n"
807 "Debug Detailed SPF Process\n"
808 )
809 {
810 unsigned char level = 0;
811 level = OSPF6_DEBUG_SPF_PROCESS;
812 OSPF6_DEBUG_SPF_ON(level);
813 return CMD_SUCCESS;
814 }
815
816 DEFUN (debug_ospf6_spf_time,
817 debug_ospf6_spf_time_cmd,
818 "debug ospf6 spf time",
819 DEBUG_STR
820 OSPF6_STR
821 "Debug SPF Calculation\n"
822 "Measure time taken by SPF Calculation\n"
823 )
824 {
825 unsigned char level = 0;
826 level = OSPF6_DEBUG_SPF_TIME;
827 OSPF6_DEBUG_SPF_ON(level);
828 return CMD_SUCCESS;
829 }
830
831 DEFUN (debug_ospf6_spf_database,
832 debug_ospf6_spf_database_cmd,
833 "debug ospf6 spf database",
834 DEBUG_STR
835 OSPF6_STR
836 "Debug SPF Calculation\n"
837 "Log number of LSAs at SPF Calculation time\n"
838 )
839 {
840 unsigned char level = 0;
841 level = OSPF6_DEBUG_SPF_DATABASE;
842 OSPF6_DEBUG_SPF_ON(level);
843 return CMD_SUCCESS;
844 }
845
846 DEFUN (no_debug_ospf6_spf_process,
847 no_debug_ospf6_spf_process_cmd,
848 "no debug ospf6 spf process",
849 NO_STR
850 DEBUG_STR
851 OSPF6_STR
852 "Quit Debugging SPF Calculation\n"
853 "Quit Debugging Detailed SPF Process\n"
854 )
855 {
856 unsigned char level = 0;
857 level = OSPF6_DEBUG_SPF_PROCESS;
858 OSPF6_DEBUG_SPF_OFF(level);
859 return CMD_SUCCESS;
860 }
861
862 DEFUN (no_debug_ospf6_spf_time,
863 no_debug_ospf6_spf_time_cmd,
864 "no debug ospf6 spf time",
865 NO_STR
866 DEBUG_STR
867 OSPF6_STR
868 "Quit Debugging SPF Calculation\n"
869 "Quit Measuring time taken by SPF Calculation\n"
870 )
871 {
872 unsigned char level = 0;
873 level = OSPF6_DEBUG_SPF_TIME;
874 OSPF6_DEBUG_SPF_OFF(level);
875 return CMD_SUCCESS;
876 }
877
878 DEFUN (no_debug_ospf6_spf_database,
879 no_debug_ospf6_spf_database_cmd,
880 "no debug ospf6 spf database",
881 NO_STR
882 DEBUG_STR
883 OSPF6_STR
884 "Debug SPF Calculation\n"
885 "Quit Logging number of LSAs at SPF Calculation time\n"
886 )
887 {
888 unsigned char level = 0;
889 level = OSPF6_DEBUG_SPF_DATABASE;
890 OSPF6_DEBUG_SPF_OFF(level);
891 return CMD_SUCCESS;
892 }
893
894 static int ospf6_timers_spf_set(struct vty *vty, unsigned int delay,
895 unsigned int hold, unsigned int max)
896 {
897 VTY_DECLVAR_CONTEXT(ospf6, ospf);
898
899 ospf->spf_delay = delay;
900 ospf->spf_holdtime = hold;
901 ospf->spf_max_holdtime = max;
902
903 return CMD_SUCCESS;
904 }
905
906 DEFUN (ospf6_timers_throttle_spf,
907 ospf6_timers_throttle_spf_cmd,
908 "timers throttle spf (0-600000) (0-600000) (0-600000)",
909 "Adjust routing timers\n"
910 "Throttling adaptive timer\n"
911 "OSPF6 SPF timers\n"
912 "Delay (msec) from first change received till SPF calculation\n"
913 "Initial hold time (msec) between consecutive SPF calculations\n"
914 "Maximum hold time (msec)\n")
915 {
916 int idx_number = 3;
917 int idx_number_2 = 4;
918 int idx_number_3 = 5;
919 unsigned int delay, hold, max;
920
921 delay = strtoul(argv[idx_number]->arg, NULL, 10);
922 hold = strtoul(argv[idx_number_2]->arg, NULL, 10);
923 max = strtoul(argv[idx_number_3]->arg, NULL, 10);
924
925 return ospf6_timers_spf_set(vty, delay, hold, max);
926 }
927
928 DEFUN (no_ospf6_timers_throttle_spf,
929 no_ospf6_timers_throttle_spf_cmd,
930 "no timers throttle spf [(0-600000) (0-600000) (0-600000)]",
931 NO_STR
932 "Adjust routing timers\n"
933 "Throttling adaptive timer\n"
934 "OSPF6 SPF timers\n"
935 "Delay (msec) from first change received till SPF calculation\n"
936 "Initial hold time (msec) between consecutive SPF calculations\n"
937 "Maximum hold time (msec)\n")
938 {
939 return ospf6_timers_spf_set(vty, OSPF_SPF_DELAY_DEFAULT,
940 OSPF_SPF_HOLDTIME_DEFAULT,
941 OSPF_SPF_MAX_HOLDTIME_DEFAULT);
942 }
943
944
945 int config_write_ospf6_debug_spf(struct vty *vty)
946 {
947 if (IS_OSPF6_DEBUG_SPF(PROCESS))
948 vty_out(vty, "debug ospf6 spf process\n");
949 if (IS_OSPF6_DEBUG_SPF(TIME))
950 vty_out(vty, "debug ospf6 spf time\n");
951 if (IS_OSPF6_DEBUG_SPF(DATABASE))
952 vty_out(vty, "debug ospf6 spf database\n");
953 return 0;
954 }
955
956 void ospf6_spf_config_write(struct vty *vty, struct ospf6 *ospf6)
957 {
958
959 if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT
960 || ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT
961 || ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
962 vty_out(vty, " timers throttle spf %d %d %d\n",
963 ospf6->spf_delay, ospf6->spf_holdtime,
964 ospf6->spf_max_holdtime);
965 }
966
967 void install_element_ospf6_debug_spf(void)
968 {
969 install_element(ENABLE_NODE, &debug_ospf6_spf_process_cmd);
970 install_element(ENABLE_NODE, &debug_ospf6_spf_time_cmd);
971 install_element(ENABLE_NODE, &debug_ospf6_spf_database_cmd);
972 install_element(ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
973 install_element(ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
974 install_element(ENABLE_NODE, &no_debug_ospf6_spf_database_cmd);
975 install_element(CONFIG_NODE, &debug_ospf6_spf_process_cmd);
976 install_element(CONFIG_NODE, &debug_ospf6_spf_time_cmd);
977 install_element(CONFIG_NODE, &debug_ospf6_spf_database_cmd);
978 install_element(CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
979 install_element(CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
980 install_element(CONFIG_NODE, &no_debug_ospf6_spf_database_cmd);
981 }
982
983 void ospf6_spf_init(void)
984 {
985 install_element(OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
986 install_element(OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
987 }
988
989 /* Create Aggregated Large Router-LSA from multiple Link-State IDs
990 * RFC 5340 A 4.3:
991 * When more than one router-LSA is received from a single router,
992 * the links are processed as if concatenated into a single LSA.*/
993 struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
994 struct ospf6_lsdb *lsdb,
995 uint32_t adv_router)
996 {
997 struct ospf6_lsa *lsa = NULL;
998 struct ospf6_lsa *rtr_lsa = NULL;
999 struct ospf6_lsa_header *lsa_header = NULL;
1000 uint8_t *new_header = NULL;
1001 const struct route_node *end = NULL;
1002 uint16_t lsa_length, total_lsa_length = 0, num_lsa = 0;
1003 uint16_t type = 0;
1004 char ifbuf[16];
1005 uint32_t interface_id;
1006 caddr_t lsd;
1007
1008 lsa_length = sizeof(struct ospf6_lsa_header)
1009 + sizeof(struct ospf6_router_lsa);
1010 total_lsa_length = lsa_length;
1011 type = htons(OSPF6_LSTYPE_ROUTER);
1012
1013 /* First check Aggregated LSA formed earlier in Cache */
1014 lsa = ospf6_lsdb_lookup(type, htonl(0), adv_router,
1015 area->temp_router_lsa_lsdb);
1016 if (lsa)
1017 return lsa;
1018
1019 inet_ntop(AF_INET, &adv_router, ifbuf, sizeof(ifbuf));
1020
1021 /* Determine total LSA length from all link state ids */
1022 end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
1023 while (rtr_lsa) {
1024 lsa = rtr_lsa;
1025 if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
1026 rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
1027 continue;
1028 }
1029 lsa_header = rtr_lsa->header;
1030 total_lsa_length += (ntohs(lsa_header->length) - lsa_length);
1031 num_lsa++;
1032 rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
1033 }
1034 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1035 zlog_debug("%s: adv_router %s num_lsa %u to convert.", __func__,
1036 ifbuf, num_lsa);
1037 if (num_lsa == 1)
1038 return lsa;
1039
1040 if (num_lsa == 0) {
1041 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1042 zlog_debug("%s: adv_router %s not found in LSDB.",
1043 __func__, ifbuf);
1044 return NULL;
1045 }
1046
1047 lsa = ospf6_lsa_alloc(total_lsa_length);
1048 new_header = (uint8_t *)lsa->header;
1049
1050 lsa->lsdb = area->temp_router_lsa_lsdb;
1051
1052 /* Fill Larger LSA Payload */
1053 end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
1054
1055 /*
1056 * We assume at this point in time that rtr_lsa is
1057 * a valid pointer.
1058 */
1059 assert(rtr_lsa);
1060 if (!OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
1061 /* Append first Link State ID LSA */
1062 lsa_header = rtr_lsa->header;
1063 memcpy(new_header, lsa_header, ntohs(lsa_header->length));
1064 /* Assign new lsa length as aggregated length. */
1065 ((struct ospf6_lsa_header *)new_header)->length =
1066 htons(total_lsa_length);
1067 new_header += ntohs(lsa_header->length);
1068 num_lsa--;
1069 }
1070
1071 /* Print LSA Name */
1072 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
1073
1074 rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
1075 while (rtr_lsa) {
1076 if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
1077 rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
1078 continue;
1079 }
1080
1081 if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
1082 lsd = OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4;
1083 interface_id = ROUTER_LSDESC_GET_IFID(lsd);
1084 inet_ntop(AF_INET, &interface_id, ifbuf, sizeof(ifbuf));
1085 zlog_debug(
1086 "%s: Next Router LSA %s to aggreat with len %u interface_id %s",
1087 __func__, rtr_lsa->name,
1088 ntohs(lsa_header->length), ifbuf);
1089 }
1090
1091 /* Append Next Link State ID LSA */
1092 lsa_header = rtr_lsa->header;
1093 memcpy(new_header, (OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4),
1094 (ntohs(lsa_header->length) - lsa_length));
1095 new_header += (ntohs(lsa_header->length) - lsa_length);
1096 num_lsa--;
1097
1098 rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
1099 }
1100
1101 /* Calculate birth of this lsa */
1102 ospf6_lsa_age_set(lsa);
1103
1104 /* Store Aggregated LSA into area temp lsdb */
1105 ospf6_lsdb_add(lsa, area->temp_router_lsa_lsdb);
1106
1107 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1108 zlog_debug("%s: LSA %s id %u type 0%x len %u num_lsa %u",
1109 __func__, lsa->name, ntohl(lsa->header->id),
1110 ntohs(lsa->header->type), ntohs(lsa->header->length),
1111 num_lsa);
1112
1113 return lsa;
1114 }
1115
1116 void ospf6_remove_temp_router_lsa(struct ospf6_area *area)
1117 {
1118 struct ospf6_lsa *lsa = NULL, *lsanext;
1119
1120 for (ALL_LSDB(area->temp_router_lsa_lsdb, lsa, lsanext)) {
1121 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1122 zlog_debug(
1123 "%s Remove LSA %s lsa->lock %u lsdb count %u",
1124 __func__, lsa->name, lsa->lock,
1125 area->temp_router_lsa_lsdb->count);
1126 ospf6_lsdb_remove(lsa, area->temp_router_lsa_lsdb);
1127 }
1128 }
1129
1130 int ospf6_ase_calculate_route(struct ospf6 *ospf6, struct ospf6_lsa *lsa,
1131 struct ospf6_area *area)
1132 {
1133 struct ospf6_route *route;
1134 struct ospf6_as_external_lsa *external;
1135 struct prefix prefix;
1136 void (*hook_add)(struct ospf6_route *) = NULL;
1137 void (*hook_remove)(struct ospf6_route *) = NULL;
1138
1139 assert(lsa);
1140
1141 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1142 zlog_debug("%s : start", __func__);
1143
1144 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7)
1145 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1146 zlog_debug("%s: Processing Type-7", __func__);
1147
1148 /* Stay away from any Local Translated Type-7 LSAs */
1149 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
1150 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1151 zlog_debug("%s: Rejecting Local translated LSA",
1152 __func__);
1153 return 0;
1154 }
1155
1156 external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
1157 lsa->header);
1158 prefix.family = AF_INET6;
1159 prefix.prefixlen = external->prefix.prefix_length;
1160 ospf6_prefix_in6_addr(&prefix.u.prefix6, external, &external->prefix);
1161
1162 if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
1163 hook_add = ospf6->route_table->hook_add;
1164 hook_remove = ospf6->route_table->hook_remove;
1165 ospf6->route_table->hook_add = NULL;
1166 ospf6->route_table->hook_remove = NULL;
1167
1168 if (!OSPF6_LSA_IS_MAXAGE(lsa))
1169 ospf6_asbr_lsa_add(lsa);
1170
1171 ospf6->route_table->hook_add = hook_add;
1172 ospf6->route_table->hook_remove = hook_remove;
1173
1174 route = ospf6_route_lookup(&prefix, ospf6->route_table);
1175 if (route == NULL) {
1176 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1177 zlog_debug("%s: no external route %pFX",
1178 __func__, &prefix);
1179 return 0;
1180 }
1181
1182 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
1183 && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
1184 UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
1185 UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
1186 }
1187
1188 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE))
1189 ospf6_route_remove(route, ospf6->route_table);
1190 else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
1191 || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
1192 if (hook_add) {
1193 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1194 zlog_debug(
1195 "%s: add external route %pFX",
1196 __func__, &prefix);
1197 (*hook_add)(route);
1198 }
1199 }
1200 } else if (ntohs(lsa->header->type) == OSPF6_LSTYPE_TYPE_7) {
1201 hook_add = area->route_table->hook_add;
1202 hook_remove = area->route_table->hook_remove;
1203 area->route_table->hook_add = NULL;
1204 area->route_table->hook_remove = NULL;
1205
1206 if (!OSPF6_LSA_IS_MAXAGE(lsa))
1207 ospf6_asbr_lsa_add(lsa);
1208
1209 area->route_table->hook_add = hook_add;
1210 area->route_table->hook_remove = hook_remove;
1211
1212 route = ospf6_route_lookup(&prefix, area->route_table);
1213 if (route == NULL) {
1214 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1215 zlog_debug("%s: no route %pFX, area %s",
1216 __func__, &prefix, area->name);
1217 return 0;
1218 }
1219
1220 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
1221 && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
1222 UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
1223 UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
1224 }
1225
1226 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) {
1227 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1228 zlog_debug("%s : remove route %pFX, area %s",
1229 __func__, &prefix, area->name);
1230 ospf6_route_remove(route, area->route_table);
1231 } else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
1232 || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
1233 if (hook_add) {
1234 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1235 zlog_debug(
1236 "%s: add nssa route %pFX, area %s",
1237 __func__, &prefix, area->name);
1238 (*hook_add)(route);
1239 }
1240 ospf6_abr_check_translate_nssa(area, lsa);
1241 }
1242 }
1243 return 0;
1244 }
1245
1246 static void ospf6_ase_calculate_timer(struct thread *t)
1247 {
1248 struct ospf6 *ospf6;
1249 struct ospf6_lsa *lsa;
1250 struct listnode *node, *nnode;
1251 struct ospf6_area *area;
1252 uint16_t type;
1253
1254 ospf6 = THREAD_ARG(t);
1255
1256 /* Calculate external route for each AS-external-LSA */
1257 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
1258 for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa))
1259 ospf6_ase_calculate_route(ospf6, lsa, NULL);
1260
1261 /* This version simple adds to the table all NSSA areas */
1262 if (ospf6->anyNSSA) {
1263 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
1264 if (IS_OSPF6_DEBUG_SPF(PROCESS))
1265 zlog_debug("%s : looking at area %s", __func__,
1266 area->name);
1267
1268 type = htons(OSPF6_LSTYPE_TYPE_7);
1269 for (ALL_LSDB_TYPED(area->lsdb, type, lsa))
1270 ospf6_ase_calculate_route(ospf6, lsa, area);
1271 }
1272 }
1273
1274 if (ospf6->gr_info.finishing_restart) {
1275 /*
1276 * The routing table computation is complete. Uninstall remnant
1277 * routes that were installed before the restart, but that are
1278 * no longer valid.
1279 */
1280 ospf6_zebra_gr_disable(ospf6);
1281 ospf6->gr_info.finishing_restart = false;
1282 }
1283 }
1284
1285 void ospf6_ase_calculate_timer_add(struct ospf6 *ospf6)
1286 {
1287 if (ospf6 == NULL)
1288 return;
1289
1290 thread_add_timer(master, ospf6_ase_calculate_timer, ospf6,
1291 OSPF6_ASE_CALC_INTERVAL, &ospf6->t_ase_calc);
1292 }