2 * Area Border Router function.
3 * Copyright (C) 2004 Yasuhiro Ohara
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "ospf6_proto.h"
35 #include "ospf6_route.h"
36 #include "ospf6_lsa.h"
37 #include "ospf6_route.h"
38 #include "ospf6_lsdb.h"
39 #include "ospf6_message.h"
40 #include "ospf6_zebra.h"
42 #include "ospf6_top.h"
43 #include "ospf6_area.h"
44 #include "ospf6_interface.h"
45 #include "ospf6_neighbor.h"
47 #include "ospf6_flood.h"
48 #include "ospf6_intra.h"
49 #include "ospf6_asbr.h"
50 #include "ospf6_abr.h"
52 #include "ospf6_nssa.h"
54 unsigned char conf_debug_ospf6_abr
;
56 int ospf6_ls_origin_same(struct ospf6_path
*o_path
, struct ospf6_path
*r_path
)
58 if (((o_path
->origin
.type
== r_path
->origin
.type
)
59 && (o_path
->origin
.id
== r_path
->origin
.id
)
60 && (o_path
->origin
.adv_router
== r_path
->origin
.adv_router
)))
66 bool ospf6_check_and_set_router_abr(struct ospf6
*o
)
68 struct listnode
*node
;
69 struct ospf6_area
*oa
;
71 bool is_backbone
= false;
73 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, node
, oa
)) {
74 if (IS_OSPF6_DEBUG_ABR
)
75 zlog_debug("%s, area_id %pI4", __func__
, &oa
->area_id
);
76 if (IS_AREA_ENABLED(oa
))
79 if (o
->backbone
== oa
)
83 if ((area_count
> 1) && (is_backbone
)) {
84 if (IS_OSPF6_DEBUG_ABR
)
85 zlog_debug("%s : set flag OSPF6_FLAG_ABR", __func__
);
86 SET_FLAG(o
->flag
, OSPF6_FLAG_ABR
);
89 if (IS_OSPF6_DEBUG_ABR
)
90 zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__
);
91 UNSET_FLAG(o
->flag
, OSPF6_FLAG_ABR
);
96 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route
*route
,
97 struct ospf6_area
*area
)
99 struct ospf6_interface
*oi
;
101 oi
= ospf6_interface_lookup_by_ifindex(
102 ospf6_route_get_first_nh_index(route
), area
->ospf6
->vrf_id
);
103 if (oi
&& oi
->area
&& oi
->area
== area
)
109 static void ospf6_abr_delete_route(struct ospf6_route
*summary
,
110 struct ospf6_route_table
*summary_table
,
111 struct ospf6_lsa
*old
)
114 ospf6_route_remove(summary
, summary_table
);
117 if (old
&& !OSPF6_LSA_IS_MAXAGE(old
))
118 ospf6_lsa_purge(old
);
121 void ospf6_abr_enable_area(struct ospf6_area
*area
)
123 struct ospf6_area
*oa
;
124 struct listnode
*node
, *nnode
;
126 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
127 /* update B bit for each area */
128 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
131 void ospf6_abr_disable_area(struct ospf6_area
*area
)
133 struct ospf6_area
*oa
;
134 struct ospf6_route
*ro
, *nro
;
135 struct ospf6_lsa
*old
;
136 struct listnode
*node
, *nnode
;
138 /* Withdraw all summary prefixes previously originated */
139 for (ro
= ospf6_route_head(area
->summary_prefix
); ro
; ro
= nro
) {
140 nro
= ospf6_route_next(ro
);
141 old
= ospf6_lsdb_lookup(ro
->path
.origin
.type
,
143 area
->ospf6
->router_id
, area
->lsdb
);
145 ospf6_lsa_purge(old
);
146 ospf6_route_remove(ro
, area
->summary_prefix
);
149 /* Withdraw all summary router-routes previously originated */
150 for (ro
= ospf6_route_head(area
->summary_router
); ro
; ro
= nro
) {
151 nro
= ospf6_route_next(ro
);
152 old
= ospf6_lsdb_lookup(ro
->path
.origin
.type
,
154 area
->ospf6
->router_id
, area
->lsdb
);
156 ospf6_lsa_purge(old
);
157 ospf6_route_remove(ro
, area
->summary_router
);
160 /* Schedule Router-LSA for each area (ABR status may change) */
161 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
162 /* update B bit for each area */
163 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
166 /* RFC 2328 12.4.3. Summary-LSAs */
167 /* Returns 1 if a summary LSA has been generated for the area */
168 /* This is used by the area/range logic to add/remove blackhole routes */
169 int ospf6_abr_originate_summary_to_area(struct ospf6_route
*route
,
170 struct ospf6_area
*area
)
172 struct ospf6_lsa
*lsa
, *old
= NULL
;
173 struct ospf6_route
*summary
, *range
= NULL
;
174 struct ospf6_area
*route_area
;
175 char buffer
[OSPF6_MAX_LSASIZE
];
176 struct ospf6_lsa_header
*lsa_header
;
178 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
179 struct ospf6_inter_router_lsa
*router_lsa
;
180 struct ospf6_route_table
*summary_table
= NULL
;
184 if (IS_OSPF6_DEBUG_ABR
) {
187 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
189 &ADV_ROUTER_IN_PREFIX(&route
->prefix
), buf
,
192 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
194 zlog_debug("%s : start area %s, route %s", __func__
, area
->name
,
198 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
199 summary_table
= area
->summary_router
;
201 summary_table
= area
->summary_prefix
;
203 summary
= ospf6_route_lookup(&route
->prefix
, summary_table
);
205 old
= ospf6_lsdb_lookup(summary
->path
.origin
.type
,
206 summary
->path
.origin
.id
,
207 area
->ospf6
->router_id
, area
->lsdb
);
208 /* Reset the OSPF6_LSA_UNAPPROVED flag */
210 UNSET_FLAG(old
->flag
, OSPF6_LSA_UNAPPROVED
);
213 /* Only destination type network, range or ASBR are considered */
214 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
215 && route
->type
!= OSPF6_DEST_TYPE_RANGE
216 && ((route
->type
!= OSPF6_DEST_TYPE_ROUTER
)
217 || !CHECK_FLAG(route
->path
.router_bits
, OSPF6_ROUTER_BIT_E
))) {
218 if (IS_OSPF6_DEBUG_ABR
)
220 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
221 __func__
, route
->type
, route
->path
.router_bits
);
225 /* AS External routes are never considered */
226 if (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
227 || route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
) {
228 if (IS_OSPF6_DEBUG_ABR
)
229 zlog_debug("%s : Path type is external, skip",
234 /* do not generate if the path's area is the same as target area */
235 if (route
->path
.area_id
== area
->area_id
) {
236 if (IS_OSPF6_DEBUG_ABR
)
238 "%s: The route is in the area itself, ignore",
243 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
247 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
250 /* Check export-list */
251 if (EXPORT_LIST(route_area
)
252 && access_list_apply(EXPORT_LIST(route_area
),
255 if (IS_OSPF6_DEBUG_ABR
)
257 "%s: prefix %pFX was denied by export-list",
258 __func__
, &route
->prefix
);
262 /* Check output prefix-list */
263 if (PREFIX_LIST_OUT(route_area
)
264 && prefix_list_apply(PREFIX_LIST_OUT(route_area
),
267 if (IS_OSPF6_DEBUG_ABR
)
269 "%s: prefix %pFX was denied by prefix-list out",
270 __func__
, &route
->prefix
);
274 /* Check import-list */
275 if (IMPORT_LIST(area
)
276 && access_list_apply(IMPORT_LIST(area
), &route
->prefix
)
278 if (IS_OSPF6_DEBUG_ABR
)
280 "%s: prefix %pFX was denied by import-list",
281 __func__
, &route
->prefix
);
285 /* Check input prefix-list */
286 if (PREFIX_LIST_IN(area
)
287 && prefix_list_apply(PREFIX_LIST_IN(area
), &route
->prefix
)
289 if (IS_OSPF6_DEBUG_ABR
)
291 "%s: prefix %pFX was denied by prefix-list in",
292 __func__
, &route
->prefix
);
298 ospf6_route_remove(summary
, summary_table
);
300 ospf6_lsa_purge(old
);
306 /* do not generate if the nexthops belongs to the target area */
307 if (ospf6_abr_nexthops_belong_to_area(route
, area
)) {
308 if (IS_OSPF6_DEBUG_ABR
)
310 "%s: The route's nexthop is in the same area, ignore",
315 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
316 if (ADV_ROUTER_IN_PREFIX(&route
->prefix
)
317 == area
->ospf6
->router_id
) {
318 if (IS_OSPF6_DEBUG_ABR
)
320 "%s: Skipping ASBR announcement for ABR (%pI4)",
322 &ADV_ROUTER_IN_PREFIX(&route
->prefix
));
327 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
328 if (IS_OSPF6_DEBUG_ABR
329 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER
)) {
331 if (IS_OSPF6_DEBUG_ABR
)
333 "Originating summary in area %s for ASBR %pI4",
335 &ADV_ROUTER_IN_PREFIX(&route
->prefix
));
338 if (IS_OSPF6_DEBUG_ABR
339 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX
))
342 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
&&
343 route
->path
.origin
.type
==
344 htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
345 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
348 "%s: route %pFX with cost %u is not best, ignore.",
349 __func__
, &route
->prefix
,
355 if (route
->path
.origin
.type
==
356 htons(OSPF6_LSTYPE_INTRA_PREFIX
)) {
357 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
360 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
361 __func__
, &route
->prefix
,
369 "Originating summary in area %s for %pFX cost %u",
370 area
->name
, &route
->prefix
, route
->path
.cost
);
373 /* if this route has just removed, remove corresponding LSA */
374 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)) {
377 "The route has just removed, purge previous LSA");
379 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
380 /* Whether the route have active longer prefix */
381 if (!CHECK_FLAG(route
->flag
,
382 OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
385 "The range is not active. withdraw");
387 ospf6_abr_delete_route(summary
, summary_table
,
391 ospf6_route_remove(summary
, summary_table
);
392 ospf6_lsa_purge(old
);
397 if ((route
->type
== OSPF6_DEST_TYPE_ROUTER
)
398 && (IS_AREA_STUB(area
) || IS_AREA_NSSA(area
))) {
401 "Area has been stubbed, purge Inter-Router LSA");
403 ospf6_abr_delete_route(summary
, summary_table
, old
);
408 && (route
->path
.subtype
!= OSPF6_PATH_SUBTYPE_DEFAULT_RT
)) {
410 zlog_debug("Area has been stubbed, purge prefix LSA");
412 ospf6_abr_delete_route(summary
, summary_table
, old
);
416 /* do not generate if the route cost is greater or equal to LSInfinity
418 if (route
->path
.cost
>= OSPF_LS_INFINITY
) {
419 /* When we're clearing the range route because all active
421 * under the range are gone, we set the range's cost to
422 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
423 * don't want to trigger the code here for that. This code is
425 * handling routes that have gone to infinity. The range removal
429 if ((route
->type
!= OSPF6_DEST_TYPE_RANGE
)
430 && (route
->path
.cost
!= OSPF_AREA_RANGE_COST_UNSPEC
)) {
433 "The cost exceeds LSInfinity, withdraw");
435 ospf6_lsa_purge(old
);
440 /* if this is a route to ASBR */
441 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
442 /* Only the preferred best path is considered */
443 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
446 "This is the secondary path to the ASBR, ignore");
447 ospf6_abr_delete_route(summary
, summary_table
, old
);
451 /* Do not generate if area is NSSA */
453 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
456 if (IS_AREA_NSSA(route_area
)) {
459 "%s: The route comes from NSSA area, skip",
461 ospf6_abr_delete_route(summary
, summary_table
, old
);
465 /* Do not generate if the area is stub */
469 /* if this is an intra-area route, this may be suppressed by aggregation
471 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
472 && route
->path
.type
== OSPF6_PATH_TYPE_INTRA
) {
473 /* search for configured address range for the route's area */
475 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
477 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
478 route_area
->range_table
);
480 /* ranges are ignored when originate backbone routes to transit
482 Otherwise, if ranges are configured, the route is suppressed.
484 if (range
&& !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)
485 && (route
->path
.area_id
!= OSPF_AREA_BACKBONE
486 || !IS_AREA_TRANSIT(area
))) {
489 "Suppressed by range %pFX of area %s",
490 &range
->prefix
, route_area
->name
);
491 /* The existing summary route could be a range, don't
492 * remove it in this case
494 if (summary
&& summary
->type
!= OSPF6_DEST_TYPE_RANGE
)
495 ospf6_abr_delete_route(summary
, summary_table
,
501 /* If this is a configured address range */
502 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
503 /* If DoNotAdvertise is set */
504 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
507 "This is the range with DoNotAdvertise set. ignore");
508 ospf6_abr_delete_route(summary
, summary_table
, old
);
512 /* If there are no active prefixes in this range, remove */
513 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
515 zlog_debug("The range is not active. withdraw");
516 ospf6_abr_delete_route(summary
, summary_table
, old
);
521 /* the route is going to be originated. store it in area's summary_table
523 if (summary
== NULL
) {
524 summary
= ospf6_route_copy(route
);
525 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
527 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
528 summary
->path
.origin
.type
=
529 htons(OSPF6_LSTYPE_INTER_ROUTER
);
530 summary
->path
.origin
.id
=
531 ADV_ROUTER_IN_PREFIX(&route
->prefix
);
533 summary
->path
.origin
.type
=
534 htons(OSPF6_LSTYPE_INTER_PREFIX
);
535 summary
->path
.origin
.id
= ospf6_new_ls_id(
536 summary
->path
.origin
.type
,
537 summary
->path
.origin
.adv_router
, area
->lsdb
);
539 summary
= ospf6_route_add(summary
, summary_table
);
541 summary
->type
= route
->type
;
542 monotime(&summary
->changed
);
545 summary
->prefix_options
= route
->prefix_options
;
546 summary
->path
.router_bits
= route
->path
.router_bits
;
547 summary
->path
.options
[0] = route
->path
.options
[0];
548 summary
->path
.options
[1] = route
->path
.options
[1];
549 summary
->path
.options
[2] = route
->path
.options
[2];
550 summary
->path
.area_id
= area
->area_id
;
551 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
552 summary
->path
.subtype
= route
->path
.subtype
;
553 summary
->path
.cost
= route
->path
.cost
;
554 /* summary->nexthop[0] = route->nexthop[0]; */
557 memset(buffer
, 0, sizeof(buffer
));
558 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
560 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
561 router_lsa
= (struct ospf6_inter_router_lsa
562 *)((caddr_t
)lsa_header
563 + sizeof(struct ospf6_lsa_header
));
564 p
= (caddr_t
)router_lsa
+ sizeof(struct ospf6_inter_router_lsa
);
566 /* Fill Inter-Area-Router-LSA */
567 router_lsa
->options
[0] = route
->path
.options
[0];
568 router_lsa
->options
[1] = route
->path
.options
[1];
569 router_lsa
->options
[2] = route
->path
.options
[2];
570 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa
, route
->path
.cost
);
571 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX(&route
->prefix
);
572 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
574 prefix_lsa
= (struct ospf6_inter_prefix_lsa
575 *)((caddr_t
)lsa_header
576 + sizeof(struct ospf6_lsa_header
));
577 p
= (caddr_t
)prefix_lsa
+ sizeof(struct ospf6_inter_prefix_lsa
);
579 /* Fill Inter-Area-Prefix-LSA */
580 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa
, route
->path
.cost
);
581 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
582 prefix_lsa
->prefix
.prefix_options
= route
->prefix_options
;
585 memcpy(p
, &route
->prefix
.u
.prefix6
,
586 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
587 ospf6_prefix_apply_mask(&prefix_lsa
->prefix
);
588 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
589 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
592 /* Fill LSA Header */
594 lsa_header
->type
= type
;
595 lsa_header
->id
= summary
->path
.origin
.id
;
596 lsa_header
->adv_router
= area
->ospf6
->router_id
;
598 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
599 lsa_header
->adv_router
, area
->lsdb
);
600 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
603 ospf6_lsa_checksum(lsa_header
);
606 lsa
= ospf6_lsa_create(lsa_header
);
608 /* Reset the unapproved flag */
609 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
612 ospf6_lsa_originate_area(lsa
, area
);
614 if (IS_OSPF6_DEBUG_ABR
)
615 zlog_debug("%s : finish area %s", __func__
, area
->name
);
620 void ospf6_abr_range_reset_cost(struct ospf6
*ospf6
)
622 struct listnode
*node
, *nnode
;
623 struct ospf6_area
*oa
;
624 struct ospf6_route
*range
;
626 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
627 for (range
= ospf6_route_head(oa
->range_table
); range
;
628 range
= ospf6_route_next(range
))
629 OSPF6_ABR_RANGE_CLEAR_COST(range
);
630 for (range
= ospf6_route_head(oa
->nssa_range_table
); range
;
631 range
= ospf6_route_next(range
))
632 OSPF6_ABR_RANGE_CLEAR_COST(range
);
636 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route
*range
,
639 struct ospf6_route
*ro
;
642 for (ro
= ospf6_route_match_head(&range
->prefix
, o
->route_table
); ro
;
643 ro
= ospf6_route_match_next(&range
->prefix
, ro
)) {
644 if (CHECK_FLAG(ro
->flag
, OSPF6_ROUTE_REMOVE
))
646 if (ro
->path
.area_id
!= range
->path
.area_id
)
648 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
649 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL1
650 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL2
)
652 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
653 && ro
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
656 cost
= MAX(cost
, ro
->path
.cost
);
663 ospf6_abr_range_summary_needs_update(struct ospf6_route
*range
, uint32_t cost
)
665 int redo_summary
= 0;
667 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
668 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
670 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
671 if (range
->path
.cost
!= 0) {
672 range
->path
.cost
= 0;
676 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
677 && range
->path
.cost
!= range
->path
.u
.cost_config
)) {
678 range
->path
.cost
= range
->path
.u
.cost_config
;
679 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
681 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
682 && range
->path
.cost
!= cost
) {
683 range
->path
.cost
= cost
;
684 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
687 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
688 /* Cost is zero, meaning no active range */
689 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
690 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
694 return (redo_summary
);
697 void ospf6_abr_range_update(struct ospf6_route
*range
, struct ospf6
*ospf6
)
700 struct listnode
*node
, *nnode
;
701 struct ospf6_area
*oa
;
702 int summary_orig
= 0;
704 assert(range
->type
== OSPF6_DEST_TYPE_RANGE
);
705 oa
= ospf6_area_lookup(range
->path
.area_id
, ospf6
);
708 /* update range's cost and active flag */
709 cost
= ospf6_abr_range_compute_cost(range
, ospf6
);
711 if (IS_OSPF6_DEBUG_ABR
)
712 zlog_debug("%s: range %pFX, cost %d", __func__
, &range
->prefix
,
715 /* Non-zero cost is a proxy for active longer prefixes in this range.
716 * If there are active routes covered by this range AND either the
718 * cost has changed or the summarized cost has changed then redo
720 * Alternately, if there are no longer active prefixes and there are
721 * summary announcements, withdraw those announcements.
723 * The don't advertise code relies on the path.cost being set to UNSPEC
725 * work the first time. Subsequent times the path.cost is not 0 anyway
727 * were active ranges.
729 if (!ospf6_abr_range_summary_needs_update(range
, cost
))
732 if (IS_OSPF6_DEBUG_ABR
)
733 zlog_debug("%s: range %pFX update", __func__
, &range
->prefix
);
735 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)) {
736 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
737 && !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
738 ospf6_nssa_lsa_originate(range
, oa
, true);
741 struct ospf6_lsa
*lsa
;
743 lsa
= ospf6_lsdb_lookup(range
->path
.origin
.type
,
744 range
->path
.origin
.id
,
745 ospf6
->router_id
, oa
->lsdb
);
747 ospf6_lsa_premature_aging(lsa
);
750 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
752 ospf6_abr_originate_summary_to_area(range
, oa
);
756 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
758 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
759 if (IS_OSPF6_DEBUG_ABR
)
760 zlog_debug("Add discard route");
762 ospf6_zebra_add_discard(range
, ospf6
);
765 /* Summary removed or no summary generated as no
767 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
768 if (IS_OSPF6_DEBUG_ABR
)
769 zlog_debug("Delete discard route");
771 ospf6_zebra_delete_discard(range
, ospf6
);
776 void ospf6_abr_originate_summary(struct ospf6_route
*route
, struct ospf6
*ospf6
)
778 struct listnode
*node
, *nnode
;
779 struct ospf6_area
*oa
;
780 struct ospf6_route
*range
= NULL
;
782 if (IS_OSPF6_DEBUG_ABR
) {
785 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
787 &ADV_ROUTER_IN_PREFIX(&route
->prefix
), buf
,
790 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
792 zlog_debug("%s: route %s", __func__
, buf
);
795 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
796 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
798 zlog_err("OSPFv6 area lookup failed");
802 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
805 ospf6_abr_range_update(range
, ospf6
);
809 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
810 ospf6_abr_originate_summary_to_area(route
, oa
);
813 void ospf6_abr_defaults_to_stub(struct ospf6
*o
)
815 struct listnode
*node
, *nnode
;
816 struct ospf6_area
*oa
;
817 struct ospf6_route
*def
, *route
;
818 int type
= DEFAULT_ROUTE
;
823 def
= ospf6_route_create(o
);
824 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
825 def
->prefix
.family
= AF_INET6
;
826 def
->prefix
.prefixlen
= 0;
827 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
828 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
829 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
830 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
831 def
->path
.area_id
= o
->backbone
->area_id
;
832 def
->path
.metric_type
= metric_type(o
, type
, 0);
833 def
->path
.cost
= metric_value(o
, type
, 0);
835 for (ALL_LIST_ELEMENTS(o
->area_list
, node
, nnode
, oa
)) {
836 if (IS_AREA_STUB(oa
) || (IS_AREA_NSSA(oa
) && oa
->no_summary
)) {
837 /* announce defaults to stubby areas */
838 if (IS_OSPF6_DEBUG_ABR
)
840 "Announcing default route into stubby area %s",
842 UNSET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
843 ospf6_abr_originate_summary_to_area(def
, oa
);
845 /* withdraw defaults when an area switches from stub to
847 route
= ospf6_route_lookup(&def
->prefix
,
850 && (route
->path
.subtype
== def
->path
.subtype
)) {
851 if (IS_OSPF6_DEBUG_ABR
)
853 "Withdrawing default route from non-stubby area %s",
855 SET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
856 ospf6_abr_originate_summary_to_area(def
, oa
);
860 ospf6_route_delete(def
);
863 void ospf6_abr_old_path_update(struct ospf6_route
*old_route
,
864 struct ospf6_route
*route
,
865 struct ospf6_route_table
*table
)
867 struct ospf6_path
*o_path
= NULL
;
868 struct listnode
*anode
, *anext
;
869 struct listnode
*nnode
, *rnode
, *rnext
;
870 struct ospf6_nexthop
*nh
, *rnh
;
872 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
, o_path
)) {
873 if (o_path
->area_id
!= route
->path
.area_id
874 || !ospf6_ls_origin_same(o_path
, &route
->path
))
877 if ((o_path
->cost
== route
->path
.cost
) &&
878 (o_path
->u
.cost_e2
== route
->path
.u
.cost_e2
))
881 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
882 for (ALL_LIST_ELEMENTS(old_route
->nh_list
, rnode
,
884 if (!ospf6_nexthop_is_same(rnh
, nh
))
886 listnode_delete(old_route
->nh_list
, rnh
);
887 ospf6_nexthop_delete(rnh
);
892 listnode_delete(old_route
->paths
, o_path
);
893 ospf6_path_free(o_path
);
895 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
,
897 ospf6_merge_nexthops(old_route
->nh_list
,
901 if (IS_OSPF6_DEBUG_ABR
|| IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
902 zlog_debug("%s: paths %u nh %u", __func__
,
904 ? listcount(old_route
->paths
)
907 ? listcount(old_route
->nh_list
)
911 (*table
->hook_add
)(old_route
);
913 if (old_route
->path
.origin
.id
== route
->path
.origin
.id
&&
914 old_route
->path
.origin
.adv_router
==
915 route
->path
.origin
.adv_router
) {
916 struct ospf6_path
*h_path
;
918 h_path
= (struct ospf6_path
*)
919 listgetdata(listhead(old_route
->paths
));
920 old_route
->path
.origin
.type
= h_path
->origin
.type
;
921 old_route
->path
.origin
.id
= h_path
->origin
.id
;
922 old_route
->path
.origin
.adv_router
=
923 h_path
->origin
.adv_router
;
928 void ospf6_abr_old_route_remove(struct ospf6_lsa
*lsa
, struct ospf6_route
*old
,
929 struct ospf6_route_table
*table
)
931 if (IS_OSPF6_DEBUG_ABR
)
932 zlog_debug("%s: route %pFX, paths %d", __func__
, &old
->prefix
,
933 listcount(old
->paths
));
935 if (listcount(old
->paths
) > 1) {
936 struct listnode
*anode
, *anext
, *nnode
, *rnode
, *rnext
;
937 struct ospf6_path
*o_path
;
938 struct ospf6_nexthop
*nh
, *rnh
;
939 bool nh_updated
= false;
941 for (ALL_LIST_ELEMENTS(old
->paths
, anode
, anext
, o_path
)) {
942 if (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
943 || o_path
->origin
.id
!= lsa
->header
->id
)
945 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
946 for (ALL_LIST_ELEMENTS(old
->nh_list
,
947 rnode
, rnext
, rnh
)) {
948 if (!ospf6_nexthop_is_same(rnh
, nh
))
950 if (IS_OSPF6_DEBUG_ABR
)
951 zlog_debug("deleted nexthop");
952 listnode_delete(old
->nh_list
, rnh
);
953 ospf6_nexthop_delete(rnh
);
956 listnode_delete(old
->paths
, o_path
);
957 ospf6_path_free(o_path
);
962 if (listcount(old
->paths
)) {
963 if (IS_OSPF6_DEBUG_ABR
964 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
965 zlog_debug("%s: old %pFX updated nh %u",
966 __func__
, &old
->prefix
,
967 old
->nh_list
? listcount(
972 (*table
->hook_add
)(old
);
974 if ((old
->path
.origin
.id
== lsa
->header
->id
) &&
975 (old
->path
.origin
.adv_router
976 == lsa
->header
->adv_router
)) {
977 struct ospf6_path
*h_path
;
979 h_path
= (struct ospf6_path
*)
981 listhead(old
->paths
));
982 old
->path
.origin
.type
=
984 old
->path
.origin
.id
= h_path
->origin
.id
;
985 old
->path
.origin
.adv_router
=
986 h_path
->origin
.adv_router
;
989 ospf6_route_remove(old
, table
);
992 ospf6_route_remove(old
, table
);
995 /* RFC 2328 16.2. Calculating the inter-area routes */
996 void ospf6_abr_examin_summary(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
998 struct prefix prefix
, abr_prefix
;
999 struct ospf6_route_table
*table
= NULL
;
1000 struct ospf6_route
*range
, *route
, *old
= NULL
, *old_route
;
1001 struct ospf6_route
*abr_entry
;
1003 char options
[3] = {0, 0, 0};
1004 uint8_t prefix_options
= 0;
1006 uint8_t router_bits
= 0;
1007 char buf
[PREFIX2STR_BUFFER
];
1009 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
1010 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
1011 bool old_entry_updated
= false;
1012 struct ospf6_path
*path
, *o_path
, *ecmp_path
;
1013 struct listnode
*anode
;
1014 bool add_route
= false;
1016 memset(&prefix
, 0, sizeof(prefix
));
1018 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1019 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
)) {
1021 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1022 lsa
->name
, ospf6_lsa_age_current(lsa
),
1027 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1029 prefix
.family
= AF_INET6
;
1030 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
1031 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, prefix_lsa
,
1032 &prefix_lsa
->prefix
);
1034 prefix2str(&prefix
, buf
, sizeof(buf
));
1035 table
= oa
->ospf6
->route_table
;
1036 type
= OSPF6_DEST_TYPE_NETWORK
;
1037 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
1038 cost
= OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
);
1039 } else if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1040 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER
)) {
1042 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1043 lsa
->name
, ospf6_lsa_age_current(lsa
),
1048 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1050 ospf6_linkstate_prefix(router_lsa
->router_id
, htonl(0),
1053 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
,
1056 table
= oa
->ospf6
->brouter_table
;
1057 type
= OSPF6_DEST_TYPE_ROUTER
;
1058 options
[0] = router_lsa
->options
[0];
1059 options
[1] = router_lsa
->options
[1];
1060 options
[2] = router_lsa
->options
[2];
1061 cost
= OSPF6_ABR_SUMMARY_METRIC(router_lsa
);
1062 SET_FLAG(router_bits
, OSPF6_ROUTER_BIT_E
);
1066 /* Find existing route */
1067 route
= ospf6_route_lookup(&prefix
, table
);
1069 ospf6_route_lock(route
);
1071 zlog_debug("%s: route %pFX, paths %d", __func__
,
1072 &prefix
, listcount(route
->paths
));
1074 while (route
&& ospf6_route_is_prefix(&prefix
, route
)) {
1075 if (route
->path
.area_id
== oa
->area_id
1076 && route
->path
.origin
.type
== lsa
->header
->type
1077 && !CHECK_FLAG(route
->flag
, OSPF6_ROUTE_WAS_REMOVED
)) {
1078 /* LSA adv. router could be part of route's
1079 * paths list. Find the existing path and set
1082 if (listcount(route
->paths
) > 1) {
1083 for (ALL_LIST_ELEMENTS_RO(route
->paths
, anode
,
1085 if (o_path
->origin
.id
== lsa
->header
->id
1086 && o_path
->origin
.adv_router
==
1087 lsa
->header
->adv_router
) {
1092 "%s: old entry found in paths, adv_router %pI4",
1094 &o_path
->origin
.adv_router
);
1099 } else if (route
->path
.origin
.id
== lsa
->header
->id
&&
1100 route
->path
.origin
.adv_router
==
1101 lsa
->header
->adv_router
)
1104 route
= ospf6_route_next(route
);
1107 ospf6_route_unlock(route
);
1109 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1110 if (cost
== OSPF_LS_INFINITY
) {
1112 zlog_debug("cost is LS_INFINITY, ignore");
1114 ospf6_abr_old_route_remove(lsa
, old
, table
);
1117 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
1119 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__
,
1122 ospf6_abr_old_route_remove(lsa
, old
, table
);
1127 /* (2) if the LSA is self-originated, ignore */
1128 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
1130 zlog_debug("LSA %s is self-originated, ignore",
1133 ospf6_route_remove(old
, table
);
1137 /* (3) if the prefix is equal to an active configured address range */
1138 /* or if the NU bit is set in the prefix */
1139 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1140 /* must have been set in previous block */
1143 range
= ospf6_route_lookup(&prefix
, oa
->range_table
);
1147 "Prefix is equal to address range, ignore");
1149 ospf6_route_remove(old
, table
);
1153 if (CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
1154 OSPF6_PREFIX_OPTION_NU
)
1155 || CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
1156 OSPF6_PREFIX_OPTION_LA
)) {
1158 zlog_debug("Prefix has NU/LA bit set, ignore");
1160 ospf6_route_remove(old
, table
);
1165 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1166 /* To pass test suites */
1168 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
1169 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
1171 zlog_debug("Prefix has NU/LA bit set, ignore");
1173 ospf6_route_remove(old
, table
);
1177 /* Avoid infinite recursion if someone has maliciously announced
1179 Inter-Router LSA for an ABR
1181 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
1184 "Ignoring Inter-Router LSA for an ABR (%s)",
1187 ospf6_route_remove(old
, table
);
1193 /* (4) if the routing table entry for the ABR does not exist */
1194 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
1195 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
1196 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
1197 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
1198 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
1201 "%s: ABR router entry %pFX does not exist, ignore",
1202 __func__
, &abr_prefix
);
1204 if (old
->type
== OSPF6_DEST_TYPE_ROUTER
&&
1205 oa
->intra_brouter_calc
) {
1208 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1209 __func__
, buf
, (void *)old
);
1213 "%s: remove old entry: %s %p ",
1214 __func__
, buf
, (void *)old
);
1215 ospf6_abr_old_route_remove(lsa
, old
, table
);
1221 /* (5),(6): the path preference is handled by the sorting
1222 in the routing table. Always install the path by substituting
1223 old route (if any). */
1224 route
= ospf6_route_create(oa
->ospf6
);
1227 route
->prefix
= prefix
;
1228 route
->prefix_options
= prefix_options
;
1229 route
->path
.origin
.type
= lsa
->header
->type
;
1230 route
->path
.origin
.id
= lsa
->header
->id
;
1231 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1232 route
->path
.router_bits
= router_bits
;
1233 route
->path
.options
[0] = options
[0];
1234 route
->path
.options
[1] = options
[1];
1235 route
->path
.options
[2] = options
[2];
1236 route
->path
.area_id
= oa
->area_id
;
1237 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
1238 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
1240 /* copy brouter rechable nexthops into the route. */
1241 ospf6_route_copy_nexthops(route
, abr_entry
);
1243 /* (7) If the routes are identical, copy the next hops over to existing
1244 route. ospf6's route table implementation will otherwise string both
1245 routes, but keep the older one as the best route since the routes
1248 old
= ospf6_route_lookup(&prefix
, table
);
1251 zlog_debug("%s: found old route %pFX, paths %d",
1252 __func__
, &prefix
, listcount(old
->paths
));
1254 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1256 /* The route linked-list is grouped in batches of prefix.
1257 * If the new prefix is not the same as the one of interest
1258 * then we have walked over the end of the batch and so we
1259 * should break rather than continuing unnecessarily.
1261 if (!ospf6_route_is_same(old_route
, route
))
1263 if ((old_route
->type
!= route
->type
)
1264 || (old_route
->path
.type
!= route
->path
.type
))
1267 if ((ospf6_route_cmp(route
, old_route
) != 0)) {
1270 "%s: old %p %pFX cost %u new route cost %u are not same",
1271 __func__
, (void *)old_route
, &prefix
,
1272 old_route
->path
.cost
, route
->path
.cost
);
1274 /* Check new route's adv. router is same in one of
1275 * the paths with differed cost, if so remove the
1276 * old path as later new route will be added.
1278 if (listcount(old_route
->paths
) > 1)
1279 ospf6_abr_old_path_update(old_route
, route
,
1284 list_delete_all_node(old_route
->nh_list
);
1285 ospf6_route_copy_nexthops(old_route
, route
);
1286 old_entry_updated
= true;
1288 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1290 if (o_path
->area_id
== route
->path
.area_id
1291 && ospf6_ls_origin_same(o_path
, &route
->path
))
1295 /* New adv. router for a existing path add to paths list */
1296 if (o_path
== NULL
) {
1297 ecmp_path
= ospf6_path_dup(&route
->path
);
1299 /* Add a nh_list to new ecmp path */
1300 ospf6_copy_nexthops(ecmp_path
->nh_list
, route
->nh_list
);
1302 /* Add the new path to route's path list */
1303 listnode_add_sort(old_route
->paths
, ecmp_path
);
1307 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1308 __func__
, &route
->prefix
,
1309 old_route
->path
.cost
,
1310 &ecmp_path
->origin
.adv_router
,
1311 listcount(ecmp_path
->nh_list
),
1313 ? listcount(old_route
->paths
)
1315 listcount(old_route
->nh_list
));
1318 struct ospf6_route
*tmp_route
;
1320 tmp_route
= ospf6_route_create(oa
->ospf6
);
1322 ospf6_copy_nexthops(tmp_route
->nh_list
,
1325 if (ospf6_route_cmp_nexthops(tmp_route
, route
) != 0) {
1326 /* adv. router exists in the list, update nhs */
1327 list_delete_all_node(o_path
->nh_list
);
1328 ospf6_copy_nexthops(o_path
->nh_list
,
1330 ospf6_route_delete(tmp_route
);
1332 /* adv. router has no change in nhs */
1333 old_entry_updated
= false;
1334 ospf6_route_delete(tmp_route
);
1341 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1342 __func__
, buf
, (void *)old_route
,
1343 old_route
->path
.cost
, route
->path
.cost
,
1344 listcount(old_route
->nh_list
));
1346 /* For Inter-Prefix route: Update RIB/FIB,
1347 * For Inter-Router trigger summary update
1349 if (table
->hook_add
)
1350 (*table
->hook_add
)(old_route
);
1355 /* If the old entry is not updated and old entry not found or old entry
1356 * does not match with the new entry then add the new route
1358 if (old_entry_updated
== false) {
1359 if ((old
== NULL
) || (old
->type
!= route
->type
)
1360 || (old
->path
.type
!= route
->path
.type
)
1361 || (old
->path
.cost
!= route
->path
.cost
))
1368 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1369 __func__
, buf
, route
->path
.cost
,
1370 listcount(route
->nh_list
),
1371 &route
->path
.origin
.adv_router
);
1374 path
= ospf6_path_dup(&route
->path
);
1375 ospf6_copy_nexthops(path
->nh_list
, abr_entry
->nh_list
);
1376 listnode_add_sort(route
->paths
, path
);
1377 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1378 ospf6_route_add(route
, table
);
1380 /* if we did not add the route remove it */
1381 ospf6_route_delete(route
);
1384 void ospf6_abr_examin_brouter(uint32_t router_id
, struct ospf6_route
*route
,
1385 struct ospf6
*ospf6
)
1387 struct ospf6_lsa
*lsa
;
1388 struct ospf6_area
*oa
;
1391 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
1393 * It is possible to designate a non backbone
1394 * area first. If that is the case safely
1395 * fall out of this function.
1400 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
1401 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1402 ospf6_abr_examin_summary(lsa
, oa
);
1404 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
1405 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1406 ospf6_abr_examin_summary(lsa
, oa
);
1409 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
1411 struct ospf6_route
*route
;
1413 if (IS_OSPF6_DEBUG_ABR
)
1414 zlog_debug("Re-examining Inter-Prefix Summaries");
1416 for (route
= ospf6_route_head(o
->route_table
); route
;
1417 route
= ospf6_route_next(route
))
1418 ospf6_abr_originate_summary(route
, o
);
1420 if (IS_OSPF6_DEBUG_ABR
)
1421 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1425 /* Display functions */
1426 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1427 char *buf
, int buflen
,
1430 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1431 struct in6_addr in6
;
1436 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1439 ospf6_prefix_in6_addr(&in6
, prefix_lsa
, &prefix_lsa
->prefix
);
1441 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1442 snprintf(tbuf
, sizeof(tbuf
), "/%d",
1443 prefix_lsa
->prefix
.prefix_length
);
1444 strlcat(buf
, tbuf
, buflen
);
1451 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1452 struct ospf6_lsa
*lsa
,
1453 json_object
*json_obj
,
1456 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1457 char buf
[INET6_ADDRSTRLEN
];
1459 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1463 json_object_int_add(
1465 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1466 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1468 json_object_string_add(json_obj
, "prefixOptions", buf
);
1469 json_object_string_add(
1471 ospf6_inter_area_prefix_lsa_get_prefix_str(
1472 lsa
, buf
, sizeof(buf
), 0));
1474 vty_out(vty
, " Metric: %lu\n",
1475 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1477 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1479 vty_out(vty
, " Prefix Options: %s\n", buf
);
1481 vty_out(vty
, " Prefix: %s\n",
1482 ospf6_inter_area_prefix_lsa_get_prefix_str(
1483 lsa
, buf
, sizeof(buf
), 0));
1489 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1490 char *buf
, int buflen
,
1493 struct ospf6_inter_router_lsa
*router_lsa
;
1497 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1502 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1508 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1509 struct ospf6_lsa
*lsa
,
1510 json_object
*json_obj
,
1513 struct ospf6_inter_router_lsa
*router_lsa
;
1516 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1519 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1521 json_object_string_add(json_obj
, "options", buf
);
1522 json_object_int_add(
1524 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1526 vty_out(vty
, " Options: %s\n", buf
);
1527 vty_out(vty
, " Metric: %lu\n",
1528 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1531 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1533 json_object_string_add(json_obj
, "destinationRouterId", buf
);
1535 vty_out(vty
, " Destination Router ID: %s\n", buf
);
1540 /* Debug commands */
1541 DEFUN (debug_ospf6_abr
,
1542 debug_ospf6_abr_cmd
,
1546 "Debug OSPFv3 ABR function\n"
1549 OSPF6_DEBUG_ABR_ON();
1553 DEFUN (no_debug_ospf6_abr
,
1554 no_debug_ospf6_abr_cmd
,
1555 "no debug ospf6 abr",
1559 "Debug OSPFv3 ABR function\n"
1562 OSPF6_DEBUG_ABR_OFF();
1566 int config_write_ospf6_debug_abr(struct vty
*vty
)
1568 if (IS_OSPF6_DEBUG_ABR
)
1569 vty_out(vty
, "debug ospf6 abr\n");
1573 void install_element_ospf6_debug_abr(void)
1575 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1576 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1577 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1578 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1581 static struct ospf6_lsa_handler inter_prefix_handler
= {
1582 .lh_type
= OSPF6_LSTYPE_INTER_PREFIX
,
1583 .lh_name
= "Inter-Prefix",
1584 .lh_short_name
= "IAP",
1585 .lh_show
= ospf6_inter_area_prefix_lsa_show
,
1586 .lh_get_prefix_str
= ospf6_inter_area_prefix_lsa_get_prefix_str
,
1589 static struct ospf6_lsa_handler inter_router_handler
= {
1590 .lh_type
= OSPF6_LSTYPE_INTER_ROUTER
,
1591 .lh_name
= "Inter-Router",
1592 .lh_short_name
= "IAR",
1593 .lh_show
= ospf6_inter_area_router_lsa_show
,
1594 .lh_get_prefix_str
= ospf6_inter_area_router_lsa_get_prefix_str
,
1597 void ospf6_abr_init(void)
1599 ospf6_install_lsa_handler(&inter_prefix_handler
);
1600 ospf6_install_lsa_handler(&inter_router_handler
);