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