]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_abr.c
Merge pull request #12967 from pguibert6WIND/show_zebra_mpls_empty
[mirror_frr.git] / ospf6d / ospf6_abr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Area Border Router function.
4 * Copyright (C) 2004 Yasuhiro Ohara
5 */
6
7 #include <zebra.h>
8
9 #include "log.h"
10 #include "prefix.h"
11 #include "table.h"
12 #include "vty.h"
13 #include "linklist.h"
14 #include "command.h"
15 #include "thread.h"
16 #include "plist.h"
17 #include "filter.h"
18
19 #include "ospf6_proto.h"
20 #include "ospf6_route.h"
21 #include "ospf6_lsa.h"
22 #include "ospf6_route.h"
23 #include "ospf6_lsdb.h"
24 #include "ospf6_message.h"
25 #include "ospf6_zebra.h"
26
27 #include "ospf6_top.h"
28 #include "ospf6_area.h"
29 #include "ospf6_interface.h"
30 #include "ospf6_neighbor.h"
31
32 #include "ospf6_flood.h"
33 #include "ospf6_intra.h"
34 #include "ospf6_asbr.h"
35 #include "ospf6_abr.h"
36 #include "ospf6d.h"
37 #include "ospf6_nssa.h"
38
39 unsigned char conf_debug_ospf6_abr;
40
41 int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path)
42 {
43 if (((o_path->origin.type == r_path->origin.type)
44 && (o_path->origin.id == r_path->origin.id)
45 && (o_path->origin.adv_router == r_path->origin.adv_router)))
46 return 1;
47 else
48 return 0;
49 }
50
51 bool ospf6_check_and_set_router_abr(struct ospf6 *o)
52 {
53 struct listnode *node;
54 struct ospf6_area *oa;
55 int area_count = 0;
56 bool is_backbone = false;
57
58 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
59 if (IS_OSPF6_DEBUG_ABR)
60 zlog_debug("%s, area_id %pI4", __func__, &oa->area_id);
61 if (IS_AREA_ENABLED(oa))
62 area_count++;
63
64 if (o->backbone == oa)
65 is_backbone = true;
66 }
67
68 if ((area_count > 1) && (is_backbone)) {
69 if (IS_OSPF6_DEBUG_ABR)
70 zlog_debug("%s : set flag OSPF6_FLAG_ABR", __func__);
71 SET_FLAG(o->flag, OSPF6_FLAG_ABR);
72 return true;
73 } else {
74 if (IS_OSPF6_DEBUG_ABR)
75 zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__);
76 UNSET_FLAG(o->flag, OSPF6_FLAG_ABR);
77 return false;
78 }
79 }
80
81 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
82 struct ospf6_area *area)
83 {
84 struct ospf6_interface *oi;
85
86 oi = ospf6_interface_lookup_by_ifindex(
87 ospf6_route_get_first_nh_index(route), area->ospf6->vrf_id);
88 if (oi && oi->area && oi->area == area)
89 return 1;
90 else
91 return 0;
92 }
93
94 static void ospf6_abr_delete_route(struct ospf6_route *summary,
95 struct ospf6_route_table *summary_table,
96 struct ospf6_lsa *old)
97 {
98 if (summary) {
99 ospf6_route_remove(summary, summary_table);
100 }
101
102 if (old && !OSPF6_LSA_IS_MAXAGE(old))
103 ospf6_lsa_purge(old);
104 }
105
106 void ospf6_abr_enable_area(struct ospf6_area *area)
107 {
108 struct ospf6_area *oa;
109 struct listnode *node, *nnode;
110
111 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
112 /* update B bit for each area */
113 OSPF6_ROUTER_LSA_SCHEDULE(oa);
114 }
115
116 void ospf6_abr_disable_area(struct ospf6_area *area)
117 {
118 struct ospf6_area *oa;
119 struct ospf6_route *ro, *nro;
120 struct ospf6_lsa *old;
121 struct listnode *node, *nnode;
122
123 /* Withdraw all summary prefixes previously originated */
124 for (ro = ospf6_route_head(area->summary_prefix); ro; ro = nro) {
125 nro = ospf6_route_next(ro);
126 old = ospf6_lsdb_lookup(ro->path.origin.type,
127 ro->path.origin.id,
128 area->ospf6->router_id, area->lsdb);
129 if (old)
130 ospf6_lsa_purge(old);
131 ospf6_route_remove(ro, area->summary_prefix);
132 }
133
134 /* Withdraw all summary router-routes previously originated */
135 for (ro = ospf6_route_head(area->summary_router); ro; ro = nro) {
136 nro = ospf6_route_next(ro);
137 old = ospf6_lsdb_lookup(ro->path.origin.type,
138 ro->path.origin.id,
139 area->ospf6->router_id, area->lsdb);
140 if (old)
141 ospf6_lsa_purge(old);
142 ospf6_route_remove(ro, area->summary_router);
143 }
144
145 /* Schedule Router-LSA for each area (ABR status may change) */
146 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
147 /* update B bit for each area */
148 OSPF6_ROUTER_LSA_SCHEDULE(oa);
149 }
150
151 /* RFC 2328 12.4.3. Summary-LSAs */
152 /* Returns 1 if a summary LSA has been generated for the area */
153 /* This is used by the area/range logic to add/remove blackhole routes */
154 int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
155 struct ospf6_area *area)
156 {
157 struct ospf6_lsa *lsa, *old = NULL;
158 struct ospf6_route *summary, *range = NULL;
159 struct ospf6_area *route_area;
160 char buffer[OSPF6_MAX_LSASIZE];
161 struct ospf6_lsa_header *lsa_header;
162 caddr_t p;
163 struct ospf6_inter_prefix_lsa *prefix_lsa;
164 struct ospf6_inter_router_lsa *router_lsa;
165 struct ospf6_route_table *summary_table = NULL;
166 uint16_t type;
167 int is_debug = 0;
168
169 if (IS_OSPF6_DEBUG_ABR) {
170 char buf[BUFSIZ];
171
172 if (route->type == OSPF6_DEST_TYPE_ROUTER)
173 inet_ntop(AF_INET,
174 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
175 sizeof(buf));
176 else
177 prefix2str(&route->prefix, buf, sizeof(buf));
178
179 zlog_debug("%s : start area %s, route %s", __func__, area->name,
180 buf);
181 }
182
183 if (route->type == OSPF6_DEST_TYPE_ROUTER)
184 summary_table = area->summary_router;
185 else
186 summary_table = area->summary_prefix;
187
188 summary = ospf6_route_lookup(&route->prefix, summary_table);
189 if (summary) {
190 old = ospf6_lsdb_lookup(summary->path.origin.type,
191 summary->path.origin.id,
192 area->ospf6->router_id, area->lsdb);
193 /* Reset the OSPF6_LSA_UNAPPROVED flag */
194 if (old)
195 UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
196 }
197
198 /* Only destination type network, range or ASBR are considered */
199 if (route->type != OSPF6_DEST_TYPE_NETWORK
200 && route->type != OSPF6_DEST_TYPE_RANGE
201 && ((route->type != OSPF6_DEST_TYPE_ROUTER)
202 || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
203 if (IS_OSPF6_DEBUG_ABR)
204 zlog_debug(
205 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
206 __func__, route->type, route->path.router_bits);
207 return 0;
208 }
209
210 /* AS External routes are never considered */
211 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
212 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
213 if (IS_OSPF6_DEBUG_ABR)
214 zlog_debug("%s : Path type is external, skip",
215 __func__);
216 return 0;
217 }
218
219 /* do not generate if the path's area is the same as target area */
220 if (route->path.area_id == area->area_id) {
221 if (IS_OSPF6_DEBUG_ABR)
222 zlog_debug(
223 "%s: The route is in the area itself, ignore",
224 __func__);
225 return 0;
226 }
227
228 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
229 bool filter = false;
230
231 route_area =
232 ospf6_area_lookup(route->path.area_id, area->ospf6);
233 assert(route_area);
234
235 /* Check export-list */
236 if (EXPORT_LIST(route_area)
237 && access_list_apply(EXPORT_LIST(route_area),
238 &route->prefix)
239 == FILTER_DENY) {
240 if (IS_OSPF6_DEBUG_ABR)
241 zlog_debug(
242 "%s: prefix %pFX was denied by export-list",
243 __func__, &route->prefix);
244 filter = true;
245 }
246
247 /* Check output prefix-list */
248 if (PREFIX_LIST_OUT(route_area)
249 && prefix_list_apply(PREFIX_LIST_OUT(route_area),
250 &route->prefix)
251 != PREFIX_PERMIT) {
252 if (IS_OSPF6_DEBUG_ABR)
253 zlog_debug(
254 "%s: prefix %pFX was denied by prefix-list out",
255 __func__, &route->prefix);
256 filter = true;
257 }
258
259 /* Check import-list */
260 if (IMPORT_LIST(area)
261 && access_list_apply(IMPORT_LIST(area), &route->prefix)
262 == FILTER_DENY) {
263 if (IS_OSPF6_DEBUG_ABR)
264 zlog_debug(
265 "%s: prefix %pFX was denied by import-list",
266 __func__, &route->prefix);
267 filter = true;
268 }
269
270 /* Check input prefix-list */
271 if (PREFIX_LIST_IN(area)
272 && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix)
273 != PREFIX_PERMIT) {
274 if (IS_OSPF6_DEBUG_ABR)
275 zlog_debug(
276 "%s: prefix %pFX was denied by prefix-list in",
277 __func__, &route->prefix);
278 filter = true;
279 }
280
281 if (filter) {
282 if (summary) {
283 ospf6_route_remove(summary, summary_table);
284 if (old)
285 ospf6_lsa_purge(old);
286 }
287 return 0;
288 }
289 }
290
291 /* do not generate if the nexthops belongs to the target area */
292 if (ospf6_abr_nexthops_belong_to_area(route, area)) {
293 if (IS_OSPF6_DEBUG_ABR)
294 zlog_debug(
295 "%s: The route's nexthop is in the same area, ignore",
296 __func__);
297 return 0;
298 }
299
300 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
301 if (ADV_ROUTER_IN_PREFIX(&route->prefix)
302 == area->ospf6->router_id) {
303 if (IS_OSPF6_DEBUG_ABR)
304 zlog_debug(
305 "%s: Skipping ASBR announcement for ABR (%pI4)",
306 __func__,
307 &ADV_ROUTER_IN_PREFIX(&route->prefix));
308 return 0;
309 }
310 }
311
312 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
313 if (IS_OSPF6_DEBUG_ABR
314 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) {
315 is_debug++;
316 if (IS_OSPF6_DEBUG_ABR)
317 zlog_debug(
318 "Originating summary in area %s for ASBR %pI4",
319 area->name,
320 &ADV_ROUTER_IN_PREFIX(&route->prefix));
321 }
322 } else {
323 if (IS_OSPF6_DEBUG_ABR
324 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX))
325 is_debug++;
326
327 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
328 route->path.origin.type ==
329 htons(OSPF6_LSTYPE_INTER_PREFIX)) {
330 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
331 if (is_debug)
332 zlog_debug(
333 "%s: route %pFX with cost %u is not best, ignore.",
334 __func__, &route->prefix,
335 route->path.cost);
336 return 0;
337 }
338 }
339
340 if (route->path.origin.type ==
341 htons(OSPF6_LSTYPE_INTRA_PREFIX)) {
342 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
343 if (is_debug)
344 zlog_debug(
345 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
346 __func__, &route->prefix,
347 route->path.cost);
348 return 0;
349 }
350 }
351
352 if (is_debug)
353 zlog_debug(
354 "Originating summary in area %s for %pFX cost %u",
355 area->name, &route->prefix, route->path.cost);
356 }
357
358 /* if this route has just removed, remove corresponding LSA */
359 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) {
360 if (is_debug)
361 zlog_debug(
362 "The route has just removed, purge previous LSA");
363
364 if (route->type == OSPF6_DEST_TYPE_RANGE) {
365 /* Whether the route have active longer prefix */
366 if (!CHECK_FLAG(route->flag,
367 OSPF6_ROUTE_ACTIVE_SUMMARY)) {
368 if (is_debug)
369 zlog_debug(
370 "The range is not active. withdraw");
371
372 ospf6_abr_delete_route(summary, summary_table,
373 old);
374 }
375 } else if (old) {
376 ospf6_route_remove(summary, summary_table);
377 ospf6_lsa_purge(old);
378 }
379 return 0;
380 }
381
382 if ((route->type == OSPF6_DEST_TYPE_ROUTER)
383 && (IS_AREA_STUB(area) || IS_AREA_NSSA(area))) {
384 if (is_debug)
385 zlog_debug(
386 "Area has been stubbed, purge Inter-Router LSA");
387
388 ospf6_abr_delete_route(summary, summary_table, old);
389 return 0;
390 }
391
392 if (area->no_summary
393 && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) {
394 if (is_debug)
395 zlog_debug("Area has been stubbed, purge prefix LSA");
396
397 ospf6_abr_delete_route(summary, summary_table, old);
398 return 0;
399 }
400
401 /* do not generate if the route cost is greater or equal to LSInfinity
402 */
403 if (route->path.cost >= OSPF_LS_INFINITY) {
404 /* When we're clearing the range route because all active
405 * prefixes
406 * under the range are gone, we set the range's cost to
407 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
408 * don't want to trigger the code here for that. This code is
409 * for
410 * handling routes that have gone to infinity. The range removal
411 * happens
412 * elsewhere.
413 */
414 if ((route->type != OSPF6_DEST_TYPE_RANGE)
415 && (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) {
416 if (is_debug)
417 zlog_debug(
418 "The cost exceeds LSInfinity, withdraw");
419 if (old)
420 ospf6_lsa_purge(old);
421 return 0;
422 }
423 }
424
425 /* if this is a route to ASBR */
426 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
427 /* Only the preferred best path is considered */
428 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
429 if (is_debug)
430 zlog_debug(
431 "This is the secondary path to the ASBR, ignore");
432 ospf6_abr_delete_route(summary, summary_table, old);
433 return 0;
434 }
435
436 /* Do not generate if area is NSSA */
437 route_area =
438 ospf6_area_lookup(route->path.area_id, area->ospf6);
439 assert(route_area);
440
441 if (IS_AREA_NSSA(route_area)) {
442 if (is_debug)
443 zlog_debug(
444 "%s: The route comes from NSSA area, skip",
445 __func__);
446 ospf6_abr_delete_route(summary, summary_table, old);
447 return 0;
448 }
449
450 /* Do not generate if the area is stub */
451 /* XXX */
452 }
453
454 /* if this is an intra-area route, this may be suppressed by aggregation
455 */
456 if (route->type == OSPF6_DEST_TYPE_NETWORK
457 && route->path.type == OSPF6_PATH_TYPE_INTRA) {
458 /* search for configured address range for the route's area */
459 route_area =
460 ospf6_area_lookup(route->path.area_id, area->ospf6);
461 assert(route_area);
462 range = ospf6_route_lookup_bestmatch(&route->prefix,
463 route_area->range_table);
464
465 /* ranges are ignored when originate backbone routes to transit
466 area.
467 Otherwise, if ranges are configured, the route is suppressed.
468 */
469 if (range && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)
470 && (route->path.area_id != OSPF_AREA_BACKBONE
471 || !IS_AREA_TRANSIT(area))) {
472 if (is_debug)
473 zlog_debug(
474 "Suppressed by range %pFX of area %s",
475 &range->prefix, route_area->name);
476 /* The existing summary route could be a range, don't
477 * remove it in this case
478 */
479 if (summary && summary->type != OSPF6_DEST_TYPE_RANGE)
480 ospf6_abr_delete_route(summary, summary_table,
481 old);
482 return 0;
483 }
484 }
485
486 /* If this is a configured address range */
487 if (route->type == OSPF6_DEST_TYPE_RANGE) {
488 /* If DoNotAdvertise is set */
489 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
490 if (is_debug)
491 zlog_debug(
492 "This is the range with DoNotAdvertise set. ignore");
493 ospf6_abr_delete_route(summary, summary_table, old);
494 return 0;
495 }
496
497 /* If there are no active prefixes in this range, remove */
498 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
499 if (is_debug)
500 zlog_debug("The range is not active. withdraw");
501 ospf6_abr_delete_route(summary, summary_table, old);
502 return 0;
503 }
504 }
505
506 /* the route is going to be originated. store it in area's summary_table
507 */
508 if (summary == NULL) {
509 summary = ospf6_route_copy(route);
510 summary->path.origin.adv_router = area->ospf6->router_id;
511
512 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
513 summary->path.origin.type =
514 htons(OSPF6_LSTYPE_INTER_ROUTER);
515 summary->path.origin.id =
516 ADV_ROUTER_IN_PREFIX(&route->prefix);
517 } else {
518 summary->path.origin.type =
519 htons(OSPF6_LSTYPE_INTER_PREFIX);
520 summary->path.origin.id = ospf6_new_ls_id(
521 summary->path.origin.type,
522 summary->path.origin.adv_router, area->lsdb);
523 }
524 summary = ospf6_route_add(summary, summary_table);
525 } else {
526 summary->type = route->type;
527 monotime(&summary->changed);
528 }
529
530 summary->prefix_options = route->prefix_options;
531 summary->path.router_bits = route->path.router_bits;
532 summary->path.options[0] = route->path.options[0];
533 summary->path.options[1] = route->path.options[1];
534 summary->path.options[2] = route->path.options[2];
535 summary->path.area_id = area->area_id;
536 summary->path.type = OSPF6_PATH_TYPE_INTER;
537 summary->path.subtype = route->path.subtype;
538 summary->path.cost = route->path.cost;
539 /* summary->nexthop[0] = route->nexthop[0]; */
540
541 /* prepare buffer */
542 memset(buffer, 0, sizeof(buffer));
543 lsa_header = (struct ospf6_lsa_header *)buffer;
544
545 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
546 router_lsa = (struct ospf6_inter_router_lsa
547 *)((caddr_t)lsa_header
548 + sizeof(struct ospf6_lsa_header));
549 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
550
551 /* Fill Inter-Area-Router-LSA */
552 router_lsa->options[0] = route->path.options[0];
553 router_lsa->options[1] = route->path.options[1];
554 router_lsa->options[2] = route->path.options[2];
555 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
556 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
557 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
558 } else {
559 prefix_lsa = (struct ospf6_inter_prefix_lsa
560 *)((caddr_t)lsa_header
561 + sizeof(struct ospf6_lsa_header));
562 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
563
564 /* Fill Inter-Area-Prefix-LSA */
565 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
566 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
567 prefix_lsa->prefix.prefix_options = route->prefix_options;
568
569 /* set Prefix */
570 memcpy(p, &route->prefix.u.prefix6,
571 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
572 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
573 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
574 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
575 }
576
577 /* Fill LSA Header */
578 lsa_header->age = 0;
579 lsa_header->type = type;
580 lsa_header->id = summary->path.origin.id;
581 lsa_header->adv_router = area->ospf6->router_id;
582 lsa_header->seqnum =
583 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
584 lsa_header->adv_router, area->lsdb);
585 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
586
587 /* LSA checksum */
588 ospf6_lsa_checksum(lsa_header);
589
590 /* create LSA */
591 lsa = ospf6_lsa_create(lsa_header);
592
593 /* Reset the unapproved flag */
594 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
595
596 /* Originate */
597 ospf6_lsa_originate_area(lsa, area);
598
599 if (IS_OSPF6_DEBUG_ABR)
600 zlog_debug("%s : finish area %s", __func__, area->name);
601
602 return 1;
603 }
604
605 void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
606 {
607 struct listnode *node, *nnode;
608 struct ospf6_area *oa;
609 struct ospf6_route *range;
610
611 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
612 for (range = ospf6_route_head(oa->range_table); range;
613 range = ospf6_route_next(range))
614 OSPF6_ABR_RANGE_CLEAR_COST(range);
615 for (range = ospf6_route_head(oa->nssa_range_table); range;
616 range = ospf6_route_next(range))
617 OSPF6_ABR_RANGE_CLEAR_COST(range);
618 }
619 }
620
621 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
622 struct ospf6 *o)
623 {
624 struct ospf6_route *ro;
625 uint32_t cost = 0;
626
627 for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
628 ro = ospf6_route_match_next(&range->prefix, ro)) {
629 if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
630 continue;
631 if (ro->path.area_id != range->path.area_id)
632 continue;
633 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
634 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
635 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
636 continue;
637 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
638 && ro->path.type != OSPF6_PATH_TYPE_INTRA)
639 continue;
640
641 cost = MAX(cost, ro->path.cost);
642 }
643
644 return cost;
645 }
646
647 static inline int
648 ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
649 {
650 int redo_summary = 0;
651
652 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
653 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
654 redo_summary = 1;
655 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
656 if (range->path.cost != 0) {
657 range->path.cost = 0;
658 redo_summary = 1;
659 }
660 } else if (cost) {
661 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
662 && range->path.cost != range->path.u.cost_config)) {
663 range->path.cost = range->path.u.cost_config;
664 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
665 redo_summary = 1;
666 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
667 && range->path.cost != cost) {
668 range->path.cost = cost;
669 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
670 redo_summary = 1;
671 }
672 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
673 /* Cost is zero, meaning no active range */
674 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
675 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
676 redo_summary = 1;
677 }
678
679 return (redo_summary);
680 }
681
682 void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
683 {
684 uint32_t cost = 0;
685 struct listnode *node, *nnode;
686 struct ospf6_area *oa;
687 int summary_orig = 0;
688
689 assert(range->type == OSPF6_DEST_TYPE_RANGE);
690 oa = ospf6_area_lookup(range->path.area_id, ospf6);
691 assert(oa);
692
693 /* update range's cost and active flag */
694 cost = ospf6_abr_range_compute_cost(range, ospf6);
695
696 if (IS_OSPF6_DEBUG_ABR)
697 zlog_debug("%s: range %pFX, cost %d", __func__, &range->prefix,
698 cost);
699
700 /* Non-zero cost is a proxy for active longer prefixes in this range.
701 * If there are active routes covered by this range AND either the
702 * configured
703 * cost has changed or the summarized cost has changed then redo
704 * summaries.
705 * Alternately, if there are no longer active prefixes and there are
706 * summary announcements, withdraw those announcements.
707 *
708 * The don't advertise code relies on the path.cost being set to UNSPEC
709 * to
710 * work the first time. Subsequent times the path.cost is not 0 anyway
711 * if there
712 * were active ranges.
713 */
714 if (!ospf6_abr_range_summary_needs_update(range, cost))
715 return;
716
717 if (IS_OSPF6_DEBUG_ABR)
718 zlog_debug("%s: range %pFX update", __func__, &range->prefix);
719
720 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
721 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
722 && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
723 ospf6_nssa_lsa_originate(range, oa, true);
724 summary_orig = 1;
725 } else {
726 struct ospf6_lsa *lsa;
727
728 lsa = ospf6_lsdb_lookup(range->path.origin.type,
729 range->path.origin.id,
730 ospf6->router_id, oa->lsdb);
731 if (lsa)
732 ospf6_lsa_premature_aging(lsa);
733 }
734 } else {
735 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
736 summary_orig +=
737 ospf6_abr_originate_summary_to_area(range, oa);
738 }
739 }
740
741 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
742 && summary_orig) {
743 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
744 if (IS_OSPF6_DEBUG_ABR)
745 zlog_debug("Add discard route");
746
747 ospf6_zebra_add_discard(range, ospf6);
748 }
749 } else {
750 /* Summary removed or no summary generated as no
751 * specifics exist */
752 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
753 if (IS_OSPF6_DEBUG_ABR)
754 zlog_debug("Delete discard route");
755
756 ospf6_zebra_delete_discard(range, ospf6);
757 }
758 }
759 }
760
761 void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
762 {
763 struct listnode *node, *nnode;
764 struct ospf6_area *oa;
765 struct ospf6_route *range = NULL;
766
767 if (IS_OSPF6_DEBUG_ABR) {
768 char buf[BUFSIZ];
769
770 if (route->type == OSPF6_DEST_TYPE_ROUTER)
771 inet_ntop(AF_INET,
772 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
773 sizeof(buf));
774 else
775 prefix2str(&route->prefix, buf, sizeof(buf));
776
777 zlog_debug("%s: route %s", __func__, buf);
778 }
779
780 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
781 oa = ospf6_area_lookup(route->path.area_id, ospf6);
782 if (!oa) {
783 zlog_err("OSPFv6 area lookup failed");
784 return;
785 }
786
787 range = ospf6_route_lookup_bestmatch(&route->prefix,
788 oa->range_table);
789 if (range) {
790 ospf6_abr_range_update(range, ospf6);
791 }
792 }
793
794 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
795 ospf6_abr_originate_summary_to_area(route, oa);
796 }
797
798 void ospf6_abr_defaults_to_stub(struct ospf6 *o)
799 {
800 struct listnode *node, *nnode;
801 struct ospf6_area *oa;
802 struct ospf6_route *def, *route;
803 int type = DEFAULT_ROUTE;
804
805 if (!o->backbone)
806 return;
807
808 def = ospf6_route_create(o);
809 def->type = OSPF6_DEST_TYPE_NETWORK;
810 def->prefix.family = AF_INET6;
811 def->prefix.prefixlen = 0;
812 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
813 def->type = OSPF6_DEST_TYPE_NETWORK;
814 def->path.type = OSPF6_PATH_TYPE_INTER;
815 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
816 def->path.area_id = o->backbone->area_id;
817 def->path.metric_type = metric_type(o, type, 0);
818 def->path.cost = metric_value(o, type, 0);
819
820 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
821 if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
822 /* announce defaults to stubby areas */
823 if (IS_OSPF6_DEBUG_ABR)
824 zlog_debug(
825 "Announcing default route into stubby area %s",
826 oa->name);
827 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
828 ospf6_abr_originate_summary_to_area(def, oa);
829 } else {
830 /* withdraw defaults when an area switches from stub to
831 * non-stub */
832 route = ospf6_route_lookup(&def->prefix,
833 oa->summary_prefix);
834 if (route
835 && (route->path.subtype == def->path.subtype)) {
836 if (IS_OSPF6_DEBUG_ABR)
837 zlog_debug(
838 "Withdrawing default route from non-stubby area %s",
839 oa->name);
840 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
841 ospf6_abr_originate_summary_to_area(def, oa);
842 }
843 }
844 }
845 ospf6_route_delete(def);
846 }
847
848 void ospf6_abr_old_path_update(struct ospf6_route *old_route,
849 struct ospf6_route *route,
850 struct ospf6_route_table *table)
851 {
852 struct ospf6_path *o_path = NULL;
853 struct listnode *anode, *anext;
854 struct listnode *nnode, *rnode, *rnext;
855 struct ospf6_nexthop *nh, *rnh;
856
857 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
858 if (o_path->area_id != route->path.area_id
859 || !ospf6_ls_origin_same(o_path, &route->path))
860 continue;
861
862 if ((o_path->cost == route->path.cost) &&
863 (o_path->u.cost_e2 == route->path.u.cost_e2))
864 continue;
865
866 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
867 for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
868 rnext, rnh)) {
869 if (!ospf6_nexthop_is_same(rnh, nh))
870 continue;
871 listnode_delete(old_route->nh_list, rnh);
872 ospf6_nexthop_delete(rnh);
873 }
874
875 }
876
877 listnode_delete(old_route->paths, o_path);
878 ospf6_path_free(o_path);
879
880 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
881 anext, o_path)) {
882 ospf6_merge_nexthops(old_route->nh_list,
883 o_path->nh_list);
884 }
885
886 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
887 zlog_debug("%s: paths %u nh %u", __func__,
888 old_route->paths
889 ? listcount(old_route->paths)
890 : 0,
891 old_route->nh_list
892 ? listcount(old_route->nh_list)
893 : 0);
894
895 if (table->hook_add)
896 (*table->hook_add)(old_route);
897
898 if (old_route->path.origin.id == route->path.origin.id &&
899 old_route->path.origin.adv_router ==
900 route->path.origin.adv_router) {
901 struct ospf6_path *h_path;
902
903 h_path = (struct ospf6_path *)
904 listgetdata(listhead(old_route->paths));
905 old_route->path.origin.type = h_path->origin.type;
906 old_route->path.origin.id = h_path->origin.id;
907 old_route->path.origin.adv_router =
908 h_path->origin.adv_router;
909 }
910 }
911 }
912
913 void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
914 struct ospf6_route_table *table)
915 {
916 if (IS_OSPF6_DEBUG_ABR)
917 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
918 listcount(old->paths));
919
920 if (listcount(old->paths) > 1) {
921 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
922 struct ospf6_path *o_path;
923 struct ospf6_nexthop *nh, *rnh;
924 bool nh_updated = false;
925
926 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
927 if (o_path->origin.adv_router != lsa->header->adv_router
928 || o_path->origin.id != lsa->header->id)
929 continue;
930 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
931 for (ALL_LIST_ELEMENTS(old->nh_list,
932 rnode, rnext, rnh)) {
933 if (!ospf6_nexthop_is_same(rnh, nh))
934 continue;
935 if (IS_OSPF6_DEBUG_ABR)
936 zlog_debug("deleted nexthop");
937 listnode_delete(old->nh_list, rnh);
938 ospf6_nexthop_delete(rnh);
939 }
940 }
941 listnode_delete(old->paths, o_path);
942 ospf6_path_free(o_path);
943 nh_updated = true;
944 }
945
946 if (nh_updated) {
947 if (listcount(old->paths)) {
948 if (IS_OSPF6_DEBUG_ABR
949 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
950 zlog_debug("%s: old %pFX updated nh %u",
951 __func__, &old->prefix,
952 old->nh_list ? listcount(
953 old->nh_list)
954 : 0);
955
956 if (table->hook_add)
957 (*table->hook_add)(old);
958
959 if ((old->path.origin.id == lsa->header->id) &&
960 (old->path.origin.adv_router
961 == lsa->header->adv_router)) {
962 struct ospf6_path *h_path;
963
964 h_path = (struct ospf6_path *)
965 listgetdata(
966 listhead(old->paths));
967 old->path.origin.type =
968 h_path->origin.type;
969 old->path.origin.id = h_path->origin.id;
970 old->path.origin.adv_router =
971 h_path->origin.adv_router;
972 }
973 } else
974 ospf6_route_remove(old, table);
975 }
976 } else
977 ospf6_route_remove(old, table);
978 }
979
980 /* RFC 2328 16.2. Calculating the inter-area routes */
981 void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
982 {
983 struct prefix prefix, abr_prefix;
984 struct ospf6_route_table *table = NULL;
985 struct ospf6_route *range, *route, *old = NULL, *old_route;
986 struct ospf6_route *abr_entry;
987 uint8_t type = 0;
988 char options[3] = {0, 0, 0};
989 uint8_t prefix_options = 0;
990 uint32_t cost = 0;
991 uint8_t router_bits = 0;
992 char buf[PREFIX2STR_BUFFER];
993 int is_debug = 0;
994 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
995 struct ospf6_inter_router_lsa *router_lsa = NULL;
996 bool old_entry_updated = false;
997 struct ospf6_path *path, *o_path, *ecmp_path;
998 struct listnode *anode;
999 bool add_route = false;
1000
1001 memset(&prefix, 0, sizeof(prefix));
1002
1003 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1004 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
1005 is_debug++;
1006 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1007 lsa->name, ospf6_lsa_age_current(lsa),
1008 oa->name);
1009 }
1010
1011 prefix_lsa =
1012 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1013 lsa->header);
1014 prefix.family = AF_INET6;
1015 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
1016 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
1017 &prefix_lsa->prefix);
1018 if (is_debug)
1019 prefix2str(&prefix, buf, sizeof(buf));
1020 table = oa->ospf6->route_table;
1021 type = OSPF6_DEST_TYPE_NETWORK;
1022 prefix_options = prefix_lsa->prefix.prefix_options;
1023 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
1024 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1025 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
1026 is_debug++;
1027 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1028 lsa->name, ospf6_lsa_age_current(lsa),
1029 oa->name);
1030 }
1031
1032 router_lsa =
1033 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1034 lsa->header);
1035 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
1036 &prefix);
1037 if (is_debug)
1038 inet_ntop(AF_INET, &router_lsa->router_id, buf,
1039 sizeof(buf));
1040
1041 table = oa->ospf6->brouter_table;
1042 type = OSPF6_DEST_TYPE_ROUTER;
1043 options[0] = router_lsa->options[0];
1044 options[1] = router_lsa->options[1];
1045 options[2] = router_lsa->options[2];
1046 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
1047 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
1048 } else
1049 assert(0);
1050
1051 /* Find existing route */
1052 route = ospf6_route_lookup(&prefix, table);
1053 if (route) {
1054 ospf6_route_lock(route);
1055 if (is_debug)
1056 zlog_debug("%s: route %pFX, paths %d", __func__,
1057 &prefix, listcount(route->paths));
1058 }
1059 while (route && ospf6_route_is_prefix(&prefix, route)) {
1060 if (route->path.area_id == oa->area_id
1061 && route->path.origin.type == lsa->header->type
1062 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
1063 /* LSA adv. router could be part of route's
1064 * paths list. Find the existing path and set
1065 * old as the route.
1066 */
1067 if (listcount(route->paths) > 1) {
1068 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
1069 o_path)) {
1070 if (o_path->origin.id == lsa->header->id
1071 && o_path->origin.adv_router ==
1072 lsa->header->adv_router) {
1073 old = route;
1074
1075 if (is_debug)
1076 zlog_debug(
1077 "%s: old entry found in paths, adv_router %pI4",
1078 __func__,
1079 &o_path->origin.adv_router);
1080
1081 break;
1082 }
1083 }
1084 } else if (route->path.origin.id == lsa->header->id &&
1085 route->path.origin.adv_router ==
1086 lsa->header->adv_router)
1087 old = route;
1088 }
1089 route = ospf6_route_next(route);
1090 }
1091 if (route)
1092 ospf6_route_unlock(route);
1093
1094 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1095 if (cost == OSPF_LS_INFINITY) {
1096 if (is_debug)
1097 zlog_debug("cost is LS_INFINITY, ignore");
1098 if (old)
1099 ospf6_abr_old_route_remove(lsa, old, table);
1100 return;
1101 }
1102 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
1103 if (is_debug)
1104 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
1105 lsa->name);
1106 if (old)
1107 ospf6_abr_old_route_remove(lsa, old, table);
1108 return;
1109 }
1110
1111
1112 /* (2) if the LSA is self-originated, ignore */
1113 if (lsa->header->adv_router == oa->ospf6->router_id) {
1114 if (is_debug)
1115 zlog_debug("LSA %s is self-originated, ignore",
1116 lsa->name);
1117 if (old)
1118 ospf6_route_remove(old, table);
1119 return;
1120 }
1121
1122 /* (3) if the prefix is equal to an active configured address range */
1123 /* or if the NU bit is set in the prefix */
1124 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1125 /* must have been set in previous block */
1126 assert(prefix_lsa);
1127
1128 range = ospf6_route_lookup(&prefix, oa->range_table);
1129 if (range) {
1130 if (is_debug)
1131 zlog_debug(
1132 "Prefix is equal to address range, ignore");
1133 if (old)
1134 ospf6_route_remove(old, table);
1135 return;
1136 }
1137
1138 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1139 OSPF6_PREFIX_OPTION_NU)) {
1140 if (is_debug)
1141 zlog_debug("Prefix has the NU bit set, ignore");
1142 if (old)
1143 ospf6_route_remove(old, table);
1144 return;
1145 }
1146 }
1147
1148 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1149 /* To pass test suites */
1150 assert(router_lsa);
1151 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
1152 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
1153 if (is_debug)
1154 zlog_debug(
1155 "Router-LSA has the V6-bit or R-bit unset, ignore");
1156 if (old)
1157 ospf6_route_remove(old, table);
1158
1159 return;
1160 }
1161 /* Avoid infinite recursion if someone has maliciously announced
1162 an
1163 Inter-Router LSA for an ABR
1164 */
1165 if (lsa->header->adv_router == router_lsa->router_id) {
1166 if (is_debug)
1167 zlog_debug(
1168 "Ignoring Inter-Router LSA for an ABR (%s)",
1169 buf);
1170 if (old)
1171 ospf6_route_remove(old, table);
1172
1173 return;
1174 }
1175 }
1176
1177 /* (4) if the routing table entry for the ABR does not exist */
1178 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
1179 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
1180 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
1181 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
1182 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
1183 if (is_debug)
1184 zlog_debug(
1185 "%s: ABR router entry %pFX does not exist, ignore",
1186 __func__, &abr_prefix);
1187 if (old) {
1188 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
1189 oa->intra_brouter_calc) {
1190 if (is_debug)
1191 zlog_debug(
1192 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1193 __func__, buf, (void *)old);
1194 } else {
1195 if (is_debug)
1196 zlog_debug(
1197 "%s: remove old entry: %s %p ",
1198 __func__, buf, (void *)old);
1199 ospf6_abr_old_route_remove(lsa, old, table);
1200 }
1201 }
1202 return;
1203 }
1204
1205 /* (5),(6): the path preference is handled by the sorting
1206 in the routing table. Always install the path by substituting
1207 old route (if any). */
1208 route = ospf6_route_create(oa->ospf6);
1209
1210 route->type = type;
1211 route->prefix = prefix;
1212 route->prefix_options = prefix_options;
1213 route->path.origin.type = lsa->header->type;
1214 route->path.origin.id = lsa->header->id;
1215 route->path.origin.adv_router = lsa->header->adv_router;
1216 route->path.router_bits = router_bits;
1217 route->path.options[0] = options[0];
1218 route->path.options[1] = options[1];
1219 route->path.options[2] = options[2];
1220 route->path.area_id = oa->area_id;
1221 route->path.type = OSPF6_PATH_TYPE_INTER;
1222 route->path.cost = abr_entry->path.cost + cost;
1223
1224 /* copy brouter rechable nexthops into the route. */
1225 ospf6_route_copy_nexthops(route, abr_entry);
1226
1227 /* (7) If the routes are identical, copy the next hops over to existing
1228 route. ospf6's route table implementation will otherwise string both
1229 routes, but keep the older one as the best route since the routes
1230 are identical.
1231 */
1232 old = ospf6_route_lookup(&prefix, table);
1233 if (old) {
1234 if (is_debug)
1235 zlog_debug("%s: found old route %pFX, paths %d",
1236 __func__, &prefix, listcount(old->paths));
1237 }
1238 for (old_route = old; old_route; old_route = old_route->next) {
1239
1240 /* The route linked-list is grouped in batches of prefix.
1241 * If the new prefix is not the same as the one of interest
1242 * then we have walked over the end of the batch and so we
1243 * should break rather than continuing unnecessarily.
1244 */
1245 if (!ospf6_route_is_same(old_route, route))
1246 break;
1247 if ((old_route->type != route->type)
1248 || (old_route->path.type != route->path.type))
1249 continue;
1250
1251 if ((ospf6_route_cmp(route, old_route) != 0)) {
1252 if (is_debug)
1253 zlog_debug(
1254 "%s: old %p %pFX cost %u new route cost %u are not same",
1255 __func__, (void *)old_route, &prefix,
1256 old_route->path.cost, route->path.cost);
1257
1258 /* Check new route's adv. router is same in one of
1259 * the paths with differed cost, if so remove the
1260 * old path as later new route will be added.
1261 */
1262 if (listcount(old_route->paths) > 1)
1263 ospf6_abr_old_path_update(old_route, route,
1264 table);
1265 continue;
1266 }
1267
1268 list_delete_all_node(old_route->nh_list);
1269 ospf6_route_copy_nexthops(old_route, route);
1270 old_entry_updated = true;
1271
1272 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1273 o_path)) {
1274 if (o_path->area_id == route->path.area_id
1275 && ospf6_ls_origin_same(o_path, &route->path))
1276 break;
1277 }
1278
1279 /* New adv. router for a existing path add to paths list */
1280 if (o_path == NULL) {
1281 ecmp_path = ospf6_path_dup(&route->path);
1282
1283 /* Add a nh_list to new ecmp path */
1284 ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
1285
1286 /* Add the new path to route's path list */
1287 listnode_add_sort(old_route->paths, ecmp_path);
1288
1289 if (is_debug) {
1290 zlog_debug(
1291 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1292 __func__, &route->prefix,
1293 old_route->path.cost,
1294 &ecmp_path->origin.adv_router,
1295 listcount(ecmp_path->nh_list),
1296 old_route->paths
1297 ? listcount(old_route->paths)
1298 : 0,
1299 listcount(old_route->nh_list));
1300 }
1301 } else {
1302 struct ospf6_route *tmp_route;
1303
1304 tmp_route = ospf6_route_create(oa->ospf6);
1305
1306 ospf6_copy_nexthops(tmp_route->nh_list,
1307 o_path->nh_list);
1308
1309 if (!ospf6_route_cmp_nexthops(tmp_route, route)) {
1310 /* adv. router exists in the list, update nhs */
1311 list_delete_all_node(o_path->nh_list);
1312 ospf6_copy_nexthops(o_path->nh_list,
1313 route->nh_list);
1314 ospf6_route_delete(tmp_route);
1315 } else {
1316 /* adv. router has no change in nhs */
1317 old_entry_updated = false;
1318 ospf6_route_delete(tmp_route);
1319 continue;
1320 }
1321 }
1322
1323 if (is_debug)
1324 zlog_debug(
1325 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1326 __func__, buf, (void *)old_route,
1327 old_route->path.cost, route->path.cost,
1328 listcount(old_route->nh_list));
1329
1330 /* For Inter-Prefix route: Update RIB/FIB,
1331 * For Inter-Router trigger summary update
1332 */
1333 if (table->hook_add)
1334 (*table->hook_add)(old_route);
1335
1336 break;
1337 }
1338
1339 /* If the old entry is not updated and old entry not found or old entry
1340 * does not match with the new entry then add the new route
1341 */
1342 if (old_entry_updated == false) {
1343 if ((old == NULL) || (old->type != route->type)
1344 || (old->path.type != route->path.type)
1345 || (old->path.cost != route->path.cost))
1346 add_route = true;
1347 }
1348
1349 if (add_route) {
1350 if (is_debug) {
1351 zlog_debug(
1352 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1353 __func__, buf, route->path.cost,
1354 listcount(route->nh_list),
1355 &route->path.origin.adv_router);
1356 }
1357
1358 path = ospf6_path_dup(&route->path);
1359 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
1360 listnode_add_sort(route->paths, path);
1361 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1362 ospf6_route_add(route, table);
1363 } else
1364 /* if we did not add the route remove it */
1365 ospf6_route_delete(route);
1366 }
1367
1368 void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
1369 struct ospf6 *ospf6)
1370 {
1371 struct ospf6_lsa *lsa;
1372 struct ospf6_area *oa;
1373 uint16_t type;
1374
1375 oa = ospf6_area_lookup(route->path.area_id, ospf6);
1376 /*
1377 * It is possible to designate a non backbone
1378 * area first. If that is the case safely
1379 * fall out of this function.
1380 */
1381 if (oa == NULL)
1382 return;
1383
1384 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1385 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1386 ospf6_abr_examin_summary(lsa, oa);
1387
1388 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1389 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1390 ospf6_abr_examin_summary(lsa, oa);
1391 }
1392
1393 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
1394 {
1395 struct ospf6_route *route;
1396
1397 if (IS_OSPF6_DEBUG_ABR)
1398 zlog_debug("Re-examining Inter-Prefix Summaries");
1399
1400 for (route = ospf6_route_head(o->route_table); route;
1401 route = ospf6_route_next(route))
1402 ospf6_abr_originate_summary(route, o);
1403
1404 if (IS_OSPF6_DEBUG_ABR)
1405 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1406 }
1407
1408
1409 /* Display functions */
1410 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1411 char *buf, int buflen,
1412 int pos)
1413 {
1414 struct ospf6_inter_prefix_lsa *prefix_lsa;
1415 struct in6_addr in6;
1416 char tbuf[16];
1417
1418 if (lsa != NULL) {
1419 prefix_lsa =
1420 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1421 lsa->header);
1422
1423 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
1424 if (buf) {
1425 inet_ntop(AF_INET6, &in6, buf, buflen);
1426 snprintf(tbuf, sizeof(tbuf), "/%d",
1427 prefix_lsa->prefix.prefix_length);
1428 strlcat(buf, tbuf, buflen);
1429 }
1430 }
1431
1432 return (buf);
1433 }
1434
1435 static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1436 struct ospf6_lsa *lsa,
1437 json_object *json_obj,
1438 bool use_json)
1439 {
1440 struct ospf6_inter_prefix_lsa *prefix_lsa;
1441 char buf[INET6_ADDRSTRLEN];
1442
1443 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1444 lsa->header);
1445
1446 if (use_json) {
1447 json_object_int_add(
1448 json_obj, "metric",
1449 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1450 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1451 buf, sizeof(buf));
1452 json_object_string_add(json_obj, "prefixOptions", buf);
1453 json_object_string_add(
1454 json_obj, "prefix",
1455 ospf6_inter_area_prefix_lsa_get_prefix_str(
1456 lsa, buf, sizeof(buf), 0));
1457 } else {
1458 vty_out(vty, " Metric: %lu\n",
1459 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1460
1461 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1462 buf, sizeof(buf));
1463 vty_out(vty, " Prefix Options: %s\n", buf);
1464
1465 vty_out(vty, " Prefix: %s\n",
1466 ospf6_inter_area_prefix_lsa_get_prefix_str(
1467 lsa, buf, sizeof(buf), 0));
1468 }
1469
1470 return 0;
1471 }
1472
1473 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1474 char *buf, int buflen,
1475 int pos)
1476 {
1477 struct ospf6_inter_router_lsa *router_lsa;
1478
1479 if (lsa != NULL) {
1480 router_lsa =
1481 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1482 lsa->header);
1483
1484
1485 if (buf)
1486 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1487 }
1488
1489 return (buf);
1490 }
1491
1492 static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1493 struct ospf6_lsa *lsa,
1494 json_object *json_obj,
1495 bool use_json)
1496 {
1497 struct ospf6_inter_router_lsa *router_lsa;
1498 char buf[64];
1499
1500 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1501 lsa->header);
1502
1503 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1504 if (use_json) {
1505 json_object_string_add(json_obj, "options", buf);
1506 json_object_int_add(
1507 json_obj, "metric",
1508 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1509 } else {
1510 vty_out(vty, " Options: %s\n", buf);
1511 vty_out(vty, " Metric: %lu\n",
1512 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1513 }
1514
1515 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1516 if (use_json)
1517 json_object_string_add(json_obj, "destinationRouterId", buf);
1518 else
1519 vty_out(vty, " Destination Router ID: %s\n", buf);
1520
1521 return 0;
1522 }
1523
1524 /* Debug commands */
1525 DEFUN (debug_ospf6_abr,
1526 debug_ospf6_abr_cmd,
1527 "debug ospf6 abr",
1528 DEBUG_STR
1529 OSPF6_STR
1530 "Debug OSPFv3 ABR function\n"
1531 )
1532 {
1533 OSPF6_DEBUG_ABR_ON();
1534 return CMD_SUCCESS;
1535 }
1536
1537 DEFUN (no_debug_ospf6_abr,
1538 no_debug_ospf6_abr_cmd,
1539 "no debug ospf6 abr",
1540 NO_STR
1541 DEBUG_STR
1542 OSPF6_STR
1543 "Debug OSPFv3 ABR function\n"
1544 )
1545 {
1546 OSPF6_DEBUG_ABR_OFF();
1547 return CMD_SUCCESS;
1548 }
1549
1550 int config_write_ospf6_debug_abr(struct vty *vty)
1551 {
1552 if (IS_OSPF6_DEBUG_ABR)
1553 vty_out(vty, "debug ospf6 abr\n");
1554 return 0;
1555 }
1556
1557 void install_element_ospf6_debug_abr(void)
1558 {
1559 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1560 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1561 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1562 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1563 }
1564
1565 static struct ospf6_lsa_handler inter_prefix_handler = {
1566 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1567 .lh_name = "Inter-Prefix",
1568 .lh_short_name = "IAP",
1569 .lh_show = ospf6_inter_area_prefix_lsa_show,
1570 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
1571 .lh_debug = 0};
1572
1573 static struct ospf6_lsa_handler inter_router_handler = {
1574 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1575 .lh_name = "Inter-Router",
1576 .lh_short_name = "IAR",
1577 .lh_show = ospf6_inter_area_router_lsa_show,
1578 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
1579 .lh_debug = 0};
1580
1581 void ospf6_abr_init(void)
1582 {
1583 ospf6_install_lsa_handler(&inter_prefix_handler);
1584 ospf6_install_lsa_handler(&inter_router_handler);
1585 }