1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Area Border Router function.
4 * Copyright (C) 2004 Yasuhiro Ohara
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"
27 #include "ospf6_top.h"
28 #include "ospf6_area.h"
29 #include "ospf6_interface.h"
30 #include "ospf6_neighbor.h"
32 #include "ospf6_flood.h"
33 #include "ospf6_intra.h"
34 #include "ospf6_asbr.h"
35 #include "ospf6_abr.h"
37 #include "ospf6_nssa.h"
39 unsigned char conf_debug_ospf6_abr
;
41 int ospf6_ls_origin_same(struct ospf6_path
*o_path
, struct ospf6_path
*r_path
)
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
)))
51 bool ospf6_check_and_set_router_abr(struct ospf6
*o
)
53 struct listnode
*node
;
54 struct ospf6_area
*oa
;
56 bool is_backbone
= false;
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
))
64 if (o
->backbone
== oa
)
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
);
74 if (IS_OSPF6_DEBUG_ABR
)
75 zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__
);
76 UNSET_FLAG(o
->flag
, OSPF6_FLAG_ABR
);
81 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route
*route
,
82 struct ospf6_area
*area
)
84 struct ospf6_interface
*oi
;
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
)
94 static void ospf6_abr_delete_route(struct ospf6_route
*summary
,
95 struct ospf6_route_table
*summary_table
,
96 struct ospf6_lsa
*old
)
99 ospf6_route_remove(summary
, summary_table
);
102 if (old
&& !OSPF6_LSA_IS_MAXAGE(old
))
103 ospf6_lsa_purge(old
);
106 void ospf6_abr_enable_area(struct ospf6_area
*area
)
108 struct ospf6_area
*oa
;
109 struct listnode
*node
, *nnode
;
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
);
116 void ospf6_abr_disable_area(struct ospf6_area
*area
)
118 struct ospf6_area
*oa
;
119 struct ospf6_route
*ro
, *nro
;
120 struct ospf6_lsa
*old
;
121 struct listnode
*node
, *nnode
;
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
,
128 area
->ospf6
->router_id
, area
->lsdb
);
130 ospf6_lsa_purge(old
);
131 ospf6_route_remove(ro
, area
->summary_prefix
);
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
,
139 area
->ospf6
->router_id
, area
->lsdb
);
141 ospf6_lsa_purge(old
);
142 ospf6_route_remove(ro
, area
->summary_router
);
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
);
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
)
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
;
163 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
164 struct ospf6_inter_router_lsa
*router_lsa
;
165 struct ospf6_route_table
*summary_table
= NULL
;
169 if (IS_OSPF6_DEBUG_ABR
) {
172 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
174 &ADV_ROUTER_IN_PREFIX(&route
->prefix
), buf
,
177 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
179 zlog_debug("%s : start area %s, route %s", __func__
, area
->name
,
183 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
184 summary_table
= area
->summary_router
;
186 summary_table
= area
->summary_prefix
;
188 summary
= ospf6_route_lookup(&route
->prefix
, summary_table
);
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 */
195 UNSET_FLAG(old
->flag
, OSPF6_LSA_UNAPPROVED
);
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
)
205 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
206 __func__
, route
->type
, route
->path
.router_bits
);
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",
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
)
223 "%s: The route is in the area itself, ignore",
228 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
232 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
235 /* Check export-list */
236 if (EXPORT_LIST(route_area
)
237 && access_list_apply(EXPORT_LIST(route_area
),
240 if (IS_OSPF6_DEBUG_ABR
)
242 "%s: prefix %pFX was denied by export-list",
243 __func__
, &route
->prefix
);
247 /* Check output prefix-list */
248 if (PREFIX_LIST_OUT(route_area
)
249 && prefix_list_apply(PREFIX_LIST_OUT(route_area
),
252 if (IS_OSPF6_DEBUG_ABR
)
254 "%s: prefix %pFX was denied by prefix-list out",
255 __func__
, &route
->prefix
);
259 /* Check import-list */
260 if (IMPORT_LIST(area
)
261 && access_list_apply(IMPORT_LIST(area
), &route
->prefix
)
263 if (IS_OSPF6_DEBUG_ABR
)
265 "%s: prefix %pFX was denied by import-list",
266 __func__
, &route
->prefix
);
270 /* Check input prefix-list */
271 if (PREFIX_LIST_IN(area
)
272 && prefix_list_apply(PREFIX_LIST_IN(area
), &route
->prefix
)
274 if (IS_OSPF6_DEBUG_ABR
)
276 "%s: prefix %pFX was denied by prefix-list in",
277 __func__
, &route
->prefix
);
283 ospf6_route_remove(summary
, summary_table
);
285 ospf6_lsa_purge(old
);
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
)
295 "%s: The route's nexthop is in the same area, ignore",
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
)
305 "%s: Skipping ASBR announcement for ABR (%pI4)",
307 &ADV_ROUTER_IN_PREFIX(&route
->prefix
));
312 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
313 if (IS_OSPF6_DEBUG_ABR
314 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER
)) {
316 if (IS_OSPF6_DEBUG_ABR
)
318 "Originating summary in area %s for ASBR %pI4",
320 &ADV_ROUTER_IN_PREFIX(&route
->prefix
));
323 if (IS_OSPF6_DEBUG_ABR
324 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX
))
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
)) {
333 "%s: route %pFX with cost %u is not best, ignore.",
334 __func__
, &route
->prefix
,
340 if (route
->path
.origin
.type
==
341 htons(OSPF6_LSTYPE_INTRA_PREFIX
)) {
342 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
345 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
346 __func__
, &route
->prefix
,
354 "Originating summary in area %s for %pFX cost %u",
355 area
->name
, &route
->prefix
, route
->path
.cost
);
358 /* if this route has just removed, remove corresponding LSA */
359 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)) {
362 "The route has just removed, purge previous LSA");
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
)) {
370 "The range is not active. withdraw");
372 ospf6_abr_delete_route(summary
, summary_table
,
376 ospf6_route_remove(summary
, summary_table
);
377 ospf6_lsa_purge(old
);
382 if ((route
->type
== OSPF6_DEST_TYPE_ROUTER
)
383 && (IS_AREA_STUB(area
) || IS_AREA_NSSA(area
))) {
386 "Area has been stubbed, purge Inter-Router LSA");
388 ospf6_abr_delete_route(summary
, summary_table
, old
);
393 && (route
->path
.subtype
!= OSPF6_PATH_SUBTYPE_DEFAULT_RT
)) {
395 zlog_debug("Area has been stubbed, purge prefix LSA");
397 ospf6_abr_delete_route(summary
, summary_table
, old
);
401 /* do not generate if the route cost is greater or equal to LSInfinity
403 if (route
->path
.cost
>= OSPF_LS_INFINITY
) {
404 /* When we're clearing the range route because all active
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
410 * handling routes that have gone to infinity. The range removal
414 if ((route
->type
!= OSPF6_DEST_TYPE_RANGE
)
415 && (route
->path
.cost
!= OSPF_AREA_RANGE_COST_UNSPEC
)) {
418 "The cost exceeds LSInfinity, withdraw");
420 ospf6_lsa_purge(old
);
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
)) {
431 "This is the secondary path to the ASBR, ignore");
432 ospf6_abr_delete_route(summary
, summary_table
, old
);
436 /* Do not generate if area is NSSA */
438 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
441 if (IS_AREA_NSSA(route_area
)) {
444 "%s: The route comes from NSSA area, skip",
446 ospf6_abr_delete_route(summary
, summary_table
, old
);
450 /* Do not generate if the area is stub */
454 /* if this is an intra-area route, this may be suppressed by aggregation
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 */
460 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
462 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
463 route_area
->range_table
);
465 /* ranges are ignored when originate backbone routes to transit
467 Otherwise, if ranges are configured, the route is suppressed.
469 if (range
&& !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)
470 && (route
->path
.area_id
!= OSPF_AREA_BACKBONE
471 || !IS_AREA_TRANSIT(area
))) {
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
479 if (summary
&& summary
->type
!= OSPF6_DEST_TYPE_RANGE
)
480 ospf6_abr_delete_route(summary
, summary_table
,
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
)) {
492 "This is the range with DoNotAdvertise set. ignore");
493 ospf6_abr_delete_route(summary
, summary_table
, old
);
497 /* If there are no active prefixes in this range, remove */
498 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
500 zlog_debug("The range is not active. withdraw");
501 ospf6_abr_delete_route(summary
, summary_table
, old
);
506 /* the route is going to be originated. store it in area's summary_table
508 if (summary
== NULL
) {
509 summary
= ospf6_route_copy(route
);
510 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
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
);
518 struct ospf6_lsa
*old
;
520 summary
->path
.origin
.type
=
521 htons(OSPF6_LSTYPE_INTER_PREFIX
);
523 /* Try to reuse LS-ID from previous running instance. */
524 old
= ospf6_find_inter_prefix_lsa(area
->ospf6
, area
,
527 summary
->path
.origin
.id
= old
->header
->id
;
529 summary
->path
.origin
.id
= ospf6_new_ls_id(
530 summary
->path
.origin
.type
,
531 summary
->path
.origin
.adv_router
,
534 summary
= ospf6_route_add(summary
, summary_table
);
536 summary
->type
= route
->type
;
537 monotime(&summary
->changed
);
540 summary
->prefix_options
= route
->prefix_options
;
541 summary
->path
.router_bits
= route
->path
.router_bits
;
542 summary
->path
.options
[0] = route
->path
.options
[0];
543 summary
->path
.options
[1] = route
->path
.options
[1];
544 summary
->path
.options
[2] = route
->path
.options
[2];
545 summary
->path
.area_id
= area
->area_id
;
546 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
547 summary
->path
.subtype
= route
->path
.subtype
;
548 summary
->path
.cost
= route
->path
.cost
;
549 /* summary->nexthop[0] = route->nexthop[0]; */
552 memset(buffer
, 0, sizeof(buffer
));
553 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
555 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
556 router_lsa
= (struct ospf6_inter_router_lsa
557 *)((caddr_t
)lsa_header
558 + sizeof(struct ospf6_lsa_header
));
559 p
= (caddr_t
)router_lsa
+ sizeof(struct ospf6_inter_router_lsa
);
561 /* Fill Inter-Area-Router-LSA */
562 router_lsa
->options
[0] = route
->path
.options
[0];
563 router_lsa
->options
[1] = route
->path
.options
[1];
564 router_lsa
->options
[2] = route
->path
.options
[2];
565 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa
, route
->path
.cost
);
566 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX(&route
->prefix
);
567 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
569 prefix_lsa
= (struct ospf6_inter_prefix_lsa
570 *)((caddr_t
)lsa_header
571 + sizeof(struct ospf6_lsa_header
));
572 p
= (caddr_t
)prefix_lsa
+ sizeof(struct ospf6_inter_prefix_lsa
);
574 /* Fill Inter-Area-Prefix-LSA */
575 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa
, route
->path
.cost
);
576 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
577 prefix_lsa
->prefix
.prefix_options
= route
->prefix_options
;
580 memcpy(p
, &route
->prefix
.u
.prefix6
,
581 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
582 ospf6_prefix_apply_mask(&prefix_lsa
->prefix
);
583 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
584 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
587 /* Fill LSA Header */
589 lsa_header
->type
= type
;
590 lsa_header
->id
= summary
->path
.origin
.id
;
591 lsa_header
->adv_router
= area
->ospf6
->router_id
;
593 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
594 lsa_header
->adv_router
, area
->lsdb
);
595 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
598 ospf6_lsa_checksum(lsa_header
);
601 lsa
= ospf6_lsa_create(lsa_header
);
603 /* Reset the unapproved flag */
604 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
607 ospf6_lsa_originate_area(lsa
, area
);
609 if (IS_OSPF6_DEBUG_ABR
)
610 zlog_debug("%s : finish area %s", __func__
, area
->name
);
615 void ospf6_abr_range_reset_cost(struct ospf6
*ospf6
)
617 struct listnode
*node
, *nnode
;
618 struct ospf6_area
*oa
;
619 struct ospf6_route
*range
;
621 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
622 for (range
= ospf6_route_head(oa
->range_table
); range
;
623 range
= ospf6_route_next(range
))
624 OSPF6_ABR_RANGE_CLEAR_COST(range
);
625 for (range
= ospf6_route_head(oa
->nssa_range_table
); range
;
626 range
= ospf6_route_next(range
))
627 OSPF6_ABR_RANGE_CLEAR_COST(range
);
631 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route
*range
,
634 struct ospf6_route
*ro
;
637 for (ro
= ospf6_route_match_head(&range
->prefix
, o
->route_table
); ro
;
638 ro
= ospf6_route_match_next(&range
->prefix
, ro
)) {
639 if (CHECK_FLAG(ro
->flag
, OSPF6_ROUTE_REMOVE
))
641 if (ro
->path
.area_id
!= range
->path
.area_id
)
643 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
644 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL1
645 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL2
)
647 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
648 && ro
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
651 cost
= MAX(cost
, ro
->path
.cost
);
658 ospf6_abr_range_summary_needs_update(struct ospf6_route
*range
, uint32_t cost
)
660 int redo_summary
= 0;
662 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
663 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
665 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
666 if (range
->path
.cost
!= 0) {
667 range
->path
.cost
= 0;
671 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
672 && range
->path
.cost
!= range
->path
.u
.cost_config
)) {
673 range
->path
.cost
= range
->path
.u
.cost_config
;
674 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
676 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
677 && range
->path
.cost
!= cost
) {
678 range
->path
.cost
= cost
;
679 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
682 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
683 /* Cost is zero, meaning no active range */
684 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
685 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
689 return (redo_summary
);
692 void ospf6_abr_range_update(struct ospf6_route
*range
, struct ospf6
*ospf6
)
695 struct listnode
*node
, *nnode
;
696 struct ospf6_area
*oa
;
697 int summary_orig
= 0;
699 assert(range
->type
== OSPF6_DEST_TYPE_RANGE
);
700 oa
= ospf6_area_lookup(range
->path
.area_id
, ospf6
);
703 /* update range's cost and active flag */
704 cost
= ospf6_abr_range_compute_cost(range
, ospf6
);
706 if (IS_OSPF6_DEBUG_ABR
)
707 zlog_debug("%s: range %pFX, cost %d", __func__
, &range
->prefix
,
710 /* Non-zero cost is a proxy for active longer prefixes in this range.
711 * If there are active routes covered by this range AND either the
713 * cost has changed or the summarized cost has changed then redo
715 * Alternately, if there are no longer active prefixes and there are
716 * summary announcements, withdraw those announcements.
718 * The don't advertise code relies on the path.cost being set to UNSPEC
720 * work the first time. Subsequent times the path.cost is not 0 anyway
722 * were active ranges.
724 if (!ospf6_abr_range_summary_needs_update(range
, cost
))
727 if (IS_OSPF6_DEBUG_ABR
)
728 zlog_debug("%s: range %pFX update", __func__
, &range
->prefix
);
730 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)) {
731 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
732 && !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
733 ospf6_nssa_lsa_originate(range
, oa
, true);
736 struct ospf6_lsa
*lsa
;
738 lsa
= ospf6_lsdb_lookup(range
->path
.origin
.type
,
739 range
->path
.origin
.id
,
740 ospf6
->router_id
, oa
->lsdb
);
742 ospf6_lsa_premature_aging(lsa
);
745 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
747 ospf6_abr_originate_summary_to_area(range
, oa
);
751 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
753 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
754 if (IS_OSPF6_DEBUG_ABR
)
755 zlog_debug("Add discard route");
757 ospf6_zebra_add_discard(range
, ospf6
);
760 /* Summary removed or no summary generated as no
762 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
763 if (IS_OSPF6_DEBUG_ABR
)
764 zlog_debug("Delete discard route");
766 ospf6_zebra_delete_discard(range
, ospf6
);
771 void ospf6_abr_originate_summary(struct ospf6_route
*route
, struct ospf6
*ospf6
)
773 struct listnode
*node
, *nnode
;
774 struct ospf6_area
*oa
;
775 struct ospf6_route
*range
= NULL
;
777 if (IS_OSPF6_DEBUG_ABR
) {
780 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
782 &ADV_ROUTER_IN_PREFIX(&route
->prefix
), buf
,
785 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
787 zlog_debug("%s: route %s", __func__
, buf
);
790 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
791 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
793 zlog_err("OSPFv6 area lookup failed");
797 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
800 ospf6_abr_range_update(range
, ospf6
);
804 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
805 ospf6_abr_originate_summary_to_area(route
, oa
);
808 void ospf6_abr_defaults_to_stub(struct ospf6
*o
)
810 struct listnode
*node
, *nnode
;
811 struct ospf6_area
*oa
;
812 struct ospf6_route
*def
, *route
;
813 int type
= DEFAULT_ROUTE
;
818 def
= ospf6_route_create(o
);
819 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
820 def
->prefix
.family
= AF_INET6
;
821 def
->prefix
.prefixlen
= 0;
822 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
823 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
824 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
825 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
826 def
->path
.area_id
= o
->backbone
->area_id
;
827 def
->path
.metric_type
= metric_type(o
, type
, 0);
828 def
->path
.cost
= metric_value(o
, type
, 0);
830 for (ALL_LIST_ELEMENTS(o
->area_list
, node
, nnode
, oa
)) {
831 if (IS_AREA_STUB(oa
) || (IS_AREA_NSSA(oa
) && oa
->no_summary
)) {
832 /* announce defaults to stubby areas */
833 if (IS_OSPF6_DEBUG_ABR
)
835 "Announcing default route into stubby area %s",
837 UNSET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
838 ospf6_abr_originate_summary_to_area(def
, oa
);
840 /* withdraw defaults when an area switches from stub to
842 route
= ospf6_route_lookup(&def
->prefix
,
845 && (route
->path
.subtype
== def
->path
.subtype
)) {
846 if (IS_OSPF6_DEBUG_ABR
)
848 "Withdrawing default route from non-stubby area %s",
850 SET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
851 ospf6_abr_originate_summary_to_area(def
, oa
);
855 ospf6_route_delete(def
);
858 void ospf6_abr_old_path_update(struct ospf6_route
*old_route
,
859 struct ospf6_route
*route
,
860 struct ospf6_route_table
*table
)
862 struct ospf6_path
*o_path
= NULL
;
863 struct listnode
*anode
, *anext
;
864 struct listnode
*nnode
, *rnode
, *rnext
;
865 struct ospf6_nexthop
*nh
, *rnh
;
867 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
, o_path
)) {
868 if (o_path
->area_id
!= route
->path
.area_id
869 || !ospf6_ls_origin_same(o_path
, &route
->path
))
872 if ((o_path
->cost
== route
->path
.cost
) &&
873 (o_path
->u
.cost_e2
== route
->path
.u
.cost_e2
))
876 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
877 for (ALL_LIST_ELEMENTS(old_route
->nh_list
, rnode
,
879 if (!ospf6_nexthop_is_same(rnh
, nh
))
881 listnode_delete(old_route
->nh_list
, rnh
);
882 ospf6_nexthop_delete(rnh
);
887 listnode_delete(old_route
->paths
, o_path
);
888 ospf6_path_free(o_path
);
890 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
,
892 ospf6_merge_nexthops(old_route
->nh_list
,
896 if (IS_OSPF6_DEBUG_ABR
|| IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
897 zlog_debug("%s: paths %u nh %u", __func__
,
899 ? listcount(old_route
->paths
)
902 ? listcount(old_route
->nh_list
)
906 (*table
->hook_add
)(old_route
);
908 if (old_route
->path
.origin
.id
== route
->path
.origin
.id
&&
909 old_route
->path
.origin
.adv_router
==
910 route
->path
.origin
.adv_router
) {
911 struct ospf6_path
*h_path
;
913 h_path
= (struct ospf6_path
*)
914 listgetdata(listhead(old_route
->paths
));
915 old_route
->path
.origin
.type
= h_path
->origin
.type
;
916 old_route
->path
.origin
.id
= h_path
->origin
.id
;
917 old_route
->path
.origin
.adv_router
=
918 h_path
->origin
.adv_router
;
923 void ospf6_abr_old_route_remove(struct ospf6_lsa
*lsa
, struct ospf6_route
*old
,
924 struct ospf6_route_table
*table
)
926 if (IS_OSPF6_DEBUG_ABR
)
927 zlog_debug("%s: route %pFX, paths %d", __func__
, &old
->prefix
,
928 listcount(old
->paths
));
930 if (listcount(old
->paths
) > 1) {
931 struct listnode
*anode
, *anext
, *nnode
, *rnode
, *rnext
;
932 struct ospf6_path
*o_path
;
933 struct ospf6_nexthop
*nh
, *rnh
;
934 bool nh_updated
= false;
936 for (ALL_LIST_ELEMENTS(old
->paths
, anode
, anext
, o_path
)) {
937 if (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
938 || o_path
->origin
.id
!= lsa
->header
->id
)
940 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
941 for (ALL_LIST_ELEMENTS(old
->nh_list
,
942 rnode
, rnext
, rnh
)) {
943 if (!ospf6_nexthop_is_same(rnh
, nh
))
945 if (IS_OSPF6_DEBUG_ABR
)
946 zlog_debug("deleted nexthop");
947 listnode_delete(old
->nh_list
, rnh
);
948 ospf6_nexthop_delete(rnh
);
951 listnode_delete(old
->paths
, o_path
);
952 ospf6_path_free(o_path
);
957 if (listcount(old
->paths
)) {
958 if (IS_OSPF6_DEBUG_ABR
959 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
960 zlog_debug("%s: old %pFX updated nh %u",
961 __func__
, &old
->prefix
,
962 old
->nh_list
? listcount(
967 (*table
->hook_add
)(old
);
969 if ((old
->path
.origin
.id
== lsa
->header
->id
) &&
970 (old
->path
.origin
.adv_router
971 == lsa
->header
->adv_router
)) {
972 struct ospf6_path
*h_path
;
974 h_path
= (struct ospf6_path
*)
976 listhead(old
->paths
));
977 old
->path
.origin
.type
=
979 old
->path
.origin
.id
= h_path
->origin
.id
;
980 old
->path
.origin
.adv_router
=
981 h_path
->origin
.adv_router
;
984 ospf6_route_remove(old
, table
);
987 ospf6_route_remove(old
, table
);
990 /* RFC 2328 16.2. Calculating the inter-area routes */
991 void ospf6_abr_examin_summary(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
993 struct prefix prefix
, abr_prefix
;
994 struct ospf6_route_table
*table
= NULL
;
995 struct ospf6_route
*range
, *route
, *old
= NULL
, *old_route
;
996 struct ospf6_route
*abr_entry
;
998 char options
[3] = {0, 0, 0};
999 uint8_t prefix_options
= 0;
1001 uint8_t router_bits
= 0;
1002 char buf
[PREFIX2STR_BUFFER
];
1004 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
1005 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
1006 bool old_entry_updated
= false;
1007 struct ospf6_path
*path
, *o_path
, *ecmp_path
;
1008 struct listnode
*anode
;
1009 bool add_route
= false;
1011 memset(&prefix
, 0, sizeof(prefix
));
1013 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1014 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
)) {
1016 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1017 lsa
->name
, ospf6_lsa_age_current(lsa
),
1022 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1024 prefix
.family
= AF_INET6
;
1025 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
1026 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, prefix_lsa
,
1027 &prefix_lsa
->prefix
);
1029 prefix2str(&prefix
, buf
, sizeof(buf
));
1030 table
= oa
->ospf6
->route_table
;
1031 type
= OSPF6_DEST_TYPE_NETWORK
;
1032 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
1033 cost
= OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
);
1034 } else if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1035 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER
)) {
1037 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1038 lsa
->name
, ospf6_lsa_age_current(lsa
),
1043 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1045 ospf6_linkstate_prefix(router_lsa
->router_id
, htonl(0),
1048 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
,
1051 table
= oa
->ospf6
->brouter_table
;
1052 type
= OSPF6_DEST_TYPE_ROUTER
;
1053 options
[0] = router_lsa
->options
[0];
1054 options
[1] = router_lsa
->options
[1];
1055 options
[2] = router_lsa
->options
[2];
1056 cost
= OSPF6_ABR_SUMMARY_METRIC(router_lsa
);
1057 SET_FLAG(router_bits
, OSPF6_ROUTER_BIT_E
);
1061 /* Find existing route */
1062 route
= ospf6_route_lookup(&prefix
, table
);
1064 ospf6_route_lock(route
);
1066 zlog_debug("%s: route %pFX, paths %d", __func__
,
1067 &prefix
, listcount(route
->paths
));
1069 while (route
&& ospf6_route_is_prefix(&prefix
, route
)) {
1070 if (route
->path
.area_id
== oa
->area_id
1071 && route
->path
.origin
.type
== lsa
->header
->type
1072 && !CHECK_FLAG(route
->flag
, OSPF6_ROUTE_WAS_REMOVED
)) {
1073 /* LSA adv. router could be part of route's
1074 * paths list. Find the existing path and set
1077 if (listcount(route
->paths
) > 1) {
1078 for (ALL_LIST_ELEMENTS_RO(route
->paths
, anode
,
1080 if (o_path
->origin
.id
== lsa
->header
->id
1081 && o_path
->origin
.adv_router
==
1082 lsa
->header
->adv_router
) {
1087 "%s: old entry found in paths, adv_router %pI4",
1089 &o_path
->origin
.adv_router
);
1094 } else if (route
->path
.origin
.id
== lsa
->header
->id
&&
1095 route
->path
.origin
.adv_router
==
1096 lsa
->header
->adv_router
)
1099 route
= ospf6_route_next(route
);
1102 ospf6_route_unlock(route
);
1104 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1105 if (cost
== OSPF_LS_INFINITY
) {
1107 zlog_debug("cost is LS_INFINITY, ignore");
1109 ospf6_abr_old_route_remove(lsa
, old
, table
);
1112 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
1114 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__
,
1117 ospf6_abr_old_route_remove(lsa
, old
, table
);
1122 /* (2) if the LSA is self-originated, ignore */
1123 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
1125 zlog_debug("LSA %s is self-originated, ignore",
1128 ospf6_route_remove(old
, table
);
1132 /* (3) if the prefix is equal to an active configured address range */
1133 /* or if the NU bit is set in the prefix */
1134 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1135 /* must have been set in previous block */
1138 range
= ospf6_route_lookup(&prefix
, oa
->range_table
);
1142 "Prefix is equal to address range, ignore");
1144 ospf6_route_remove(old
, table
);
1148 if (CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
1149 OSPF6_PREFIX_OPTION_NU
)) {
1151 zlog_debug("Prefix has the NU bit set, ignore");
1153 ospf6_route_remove(old
, table
);
1158 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1159 /* To pass test suites */
1161 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
1162 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
1165 "Router-LSA has the V6-bit or R-bit unset, ignore");
1167 ospf6_route_remove(old
, table
);
1171 /* Avoid infinite recursion if someone has maliciously announced
1173 Inter-Router LSA for an ABR
1175 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
1178 "Ignoring Inter-Router LSA for an ABR (%s)",
1181 ospf6_route_remove(old
, table
);
1187 /* (4) if the routing table entry for the ABR does not exist */
1188 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
1189 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
1190 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
1191 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
1192 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
1195 "%s: ABR router entry %pFX does not exist, ignore",
1196 __func__
, &abr_prefix
);
1198 if (old
->type
== OSPF6_DEST_TYPE_ROUTER
&&
1199 oa
->intra_brouter_calc
) {
1202 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1203 __func__
, buf
, (void *)old
);
1207 "%s: remove old entry: %s %p ",
1208 __func__
, buf
, (void *)old
);
1209 ospf6_abr_old_route_remove(lsa
, old
, table
);
1215 /* (5),(6): the path preference is handled by the sorting
1216 in the routing table. Always install the path by substituting
1217 old route (if any). */
1218 route
= ospf6_route_create(oa
->ospf6
);
1221 route
->prefix
= prefix
;
1222 route
->prefix_options
= prefix_options
;
1223 route
->path
.origin
.type
= lsa
->header
->type
;
1224 route
->path
.origin
.id
= lsa
->header
->id
;
1225 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1226 route
->path
.router_bits
= router_bits
;
1227 route
->path
.options
[0] = options
[0];
1228 route
->path
.options
[1] = options
[1];
1229 route
->path
.options
[2] = options
[2];
1230 route
->path
.area_id
= oa
->area_id
;
1231 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
1232 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
1234 /* copy brouter rechable nexthops into the route. */
1235 ospf6_route_copy_nexthops(route
, abr_entry
);
1237 /* (7) If the routes are identical, copy the next hops over to existing
1238 route. ospf6's route table implementation will otherwise string both
1239 routes, but keep the older one as the best route since the routes
1242 old
= ospf6_route_lookup(&prefix
, table
);
1245 zlog_debug("%s: found old route %pFX, paths %d",
1246 __func__
, &prefix
, listcount(old
->paths
));
1248 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1250 /* The route linked-list is grouped in batches of prefix.
1251 * If the new prefix is not the same as the one of interest
1252 * then we have walked over the end of the batch and so we
1253 * should break rather than continuing unnecessarily.
1255 if (!ospf6_route_is_same(old_route
, route
))
1257 if ((old_route
->type
!= route
->type
)
1258 || (old_route
->path
.type
!= route
->path
.type
))
1261 if ((ospf6_route_cmp(route
, old_route
) != 0)) {
1264 "%s: old %p %pFX cost %u new route cost %u are not same",
1265 __func__
, (void *)old_route
, &prefix
,
1266 old_route
->path
.cost
, route
->path
.cost
);
1268 /* Check new route's adv. router is same in one of
1269 * the paths with differed cost, if so remove the
1270 * old path as later new route will be added.
1272 if (listcount(old_route
->paths
) > 1)
1273 ospf6_abr_old_path_update(old_route
, route
,
1278 list_delete_all_node(old_route
->nh_list
);
1279 ospf6_route_copy_nexthops(old_route
, route
);
1280 old_entry_updated
= true;
1282 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1284 if (o_path
->area_id
== route
->path
.area_id
1285 && ospf6_ls_origin_same(o_path
, &route
->path
))
1289 /* New adv. router for a existing path add to paths list */
1290 if (o_path
== NULL
) {
1291 ecmp_path
= ospf6_path_dup(&route
->path
);
1293 /* Add a nh_list to new ecmp path */
1294 ospf6_copy_nexthops(ecmp_path
->nh_list
, route
->nh_list
);
1296 /* Add the new path to route's path list */
1297 listnode_add_sort(old_route
->paths
, ecmp_path
);
1301 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1302 __func__
, &route
->prefix
,
1303 old_route
->path
.cost
,
1304 &ecmp_path
->origin
.adv_router
,
1305 listcount(ecmp_path
->nh_list
),
1307 ? listcount(old_route
->paths
)
1309 listcount(old_route
->nh_list
));
1312 struct ospf6_route
*tmp_route
;
1314 tmp_route
= ospf6_route_create(oa
->ospf6
);
1316 ospf6_copy_nexthops(tmp_route
->nh_list
,
1319 if (!ospf6_route_cmp_nexthops(tmp_route
, route
)) {
1320 /* adv. router exists in the list, update nhs */
1321 list_delete_all_node(o_path
->nh_list
);
1322 ospf6_copy_nexthops(o_path
->nh_list
,
1324 ospf6_route_delete(tmp_route
);
1326 /* adv. router has no change in nhs */
1327 old_entry_updated
= false;
1328 ospf6_route_delete(tmp_route
);
1335 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1336 __func__
, buf
, (void *)old_route
,
1337 old_route
->path
.cost
, route
->path
.cost
,
1338 listcount(old_route
->nh_list
));
1340 /* For Inter-Prefix route: Update RIB/FIB,
1341 * For Inter-Router trigger summary update
1343 if (table
->hook_add
)
1344 (*table
->hook_add
)(old_route
);
1349 /* If the old entry is not updated and old entry not found or old entry
1350 * does not match with the new entry then add the new route
1352 if (old_entry_updated
== false) {
1353 if ((old
== NULL
) || (old
->type
!= route
->type
)
1354 || (old
->path
.type
!= route
->path
.type
)
1355 || (old
->path
.cost
!= route
->path
.cost
))
1362 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1363 __func__
, buf
, route
->path
.cost
,
1364 listcount(route
->nh_list
),
1365 &route
->path
.origin
.adv_router
);
1368 path
= ospf6_path_dup(&route
->path
);
1369 ospf6_copy_nexthops(path
->nh_list
, abr_entry
->nh_list
);
1370 listnode_add_sort(route
->paths
, path
);
1371 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1372 ospf6_route_add(route
, table
);
1374 /* if we did not add the route remove it */
1375 ospf6_route_delete(route
);
1378 void ospf6_abr_examin_brouter(uint32_t router_id
, struct ospf6_route
*route
,
1379 struct ospf6
*ospf6
)
1381 struct ospf6_lsa
*lsa
;
1382 struct ospf6_area
*oa
;
1385 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
1387 * It is possible to designate a non backbone
1388 * area first. If that is the case safely
1389 * fall out of this function.
1394 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
1395 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1396 ospf6_abr_examin_summary(lsa
, oa
);
1398 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
1399 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1400 ospf6_abr_examin_summary(lsa
, oa
);
1403 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
1405 struct ospf6_route
*route
;
1407 if (IS_OSPF6_DEBUG_ABR
)
1408 zlog_debug("Re-examining Inter-Prefix Summaries");
1410 for (route
= ospf6_route_head(o
->route_table
); route
;
1411 route
= ospf6_route_next(route
))
1412 ospf6_abr_originate_summary(route
, o
);
1414 if (IS_OSPF6_DEBUG_ABR
)
1415 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1419 /* Display functions */
1420 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1421 char *buf
, int buflen
,
1424 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1425 struct in6_addr in6
;
1430 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1433 ospf6_prefix_in6_addr(&in6
, prefix_lsa
, &prefix_lsa
->prefix
);
1435 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1436 snprintf(tbuf
, sizeof(tbuf
), "/%d",
1437 prefix_lsa
->prefix
.prefix_length
);
1438 strlcat(buf
, tbuf
, buflen
);
1445 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1446 struct ospf6_lsa
*lsa
,
1447 json_object
*json_obj
,
1450 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1451 char buf
[INET6_ADDRSTRLEN
];
1453 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1457 json_object_int_add(
1459 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1460 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1462 json_object_string_add(json_obj
, "prefixOptions", buf
);
1463 json_object_string_add(
1465 ospf6_inter_area_prefix_lsa_get_prefix_str(
1466 lsa
, buf
, sizeof(buf
), 0));
1468 vty_out(vty
, " Metric: %lu\n",
1469 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1471 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1473 vty_out(vty
, " Prefix Options: %s\n", buf
);
1475 vty_out(vty
, " Prefix: %s\n",
1476 ospf6_inter_area_prefix_lsa_get_prefix_str(
1477 lsa
, buf
, sizeof(buf
), 0));
1483 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1484 char *buf
, int buflen
,
1487 struct ospf6_inter_router_lsa
*router_lsa
;
1491 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1496 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1502 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1503 struct ospf6_lsa
*lsa
,
1504 json_object
*json_obj
,
1507 struct ospf6_inter_router_lsa
*router_lsa
;
1510 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1513 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1515 json_object_string_add(json_obj
, "options", buf
);
1516 json_object_int_add(
1518 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1520 vty_out(vty
, " Options: %s\n", buf
);
1521 vty_out(vty
, " Metric: %lu\n",
1522 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1525 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1527 json_object_string_add(json_obj
, "destinationRouterId", buf
);
1529 vty_out(vty
, " Destination Router ID: %s\n", buf
);
1534 /* Debug commands */
1535 DEFUN (debug_ospf6_abr
,
1536 debug_ospf6_abr_cmd
,
1540 "Debug OSPFv3 ABR function\n"
1543 OSPF6_DEBUG_ABR_ON();
1547 DEFUN (no_debug_ospf6_abr
,
1548 no_debug_ospf6_abr_cmd
,
1549 "no debug ospf6 abr",
1553 "Debug OSPFv3 ABR function\n"
1556 OSPF6_DEBUG_ABR_OFF();
1560 int config_write_ospf6_debug_abr(struct vty
*vty
)
1562 if (IS_OSPF6_DEBUG_ABR
)
1563 vty_out(vty
, "debug ospf6 abr\n");
1567 void install_element_ospf6_debug_abr(void)
1569 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1570 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1571 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1572 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1575 static struct ospf6_lsa_handler inter_prefix_handler
= {
1576 .lh_type
= OSPF6_LSTYPE_INTER_PREFIX
,
1577 .lh_name
= "Inter-Prefix",
1578 .lh_short_name
= "IAP",
1579 .lh_show
= ospf6_inter_area_prefix_lsa_show
,
1580 .lh_get_prefix_str
= ospf6_inter_area_prefix_lsa_get_prefix_str
,
1583 static struct ospf6_lsa_handler inter_router_handler
= {
1584 .lh_type
= OSPF6_LSTYPE_INTER_ROUTER
,
1585 .lh_name
= "Inter-Router",
1586 .lh_short_name
= "IAR",
1587 .lh_show
= ospf6_inter_area_router_lsa_show
,
1588 .lh_get_prefix_str
= ospf6_inter_area_router_lsa_get_prefix_str
,
1591 void ospf6_abr_init(void)
1593 ospf6_install_lsa_handler(&inter_prefix_handler
);
1594 ospf6_install_lsa_handler(&inter_router_handler
);