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