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