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 ospf6_abr_delete_route(summary
, summary_table
, old
);
496 /* If this is a configured address range */
497 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
498 /* If DoNotAdvertise is set */
499 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
502 "This is the range with DoNotAdvertise set. ignore");
503 ospf6_abr_delete_route(summary
, summary_table
, old
);
507 /* If there are no active prefixes in this range, remove */
508 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
510 zlog_debug("The range is not active. withdraw");
511 ospf6_abr_delete_route(summary
, summary_table
, old
);
516 /* the route is going to be originated. store it in area's summary_table
518 if (summary
== NULL
) {
519 summary
= ospf6_route_copy(route
);
520 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
522 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
523 summary
->path
.origin
.type
=
524 htons(OSPF6_LSTYPE_INTER_ROUTER
);
525 summary
->path
.origin
.id
=
526 ADV_ROUTER_IN_PREFIX(&route
->prefix
);
528 summary
->path
.origin
.type
=
529 htons(OSPF6_LSTYPE_INTER_PREFIX
);
530 summary
->path
.origin
.id
= ospf6_new_ls_id(
531 summary
->path
.origin
.type
,
532 summary
->path
.origin
.adv_router
, area
->lsdb
);
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
)
1150 || CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
1151 OSPF6_PREFIX_OPTION_LA
)) {
1153 zlog_debug("Prefix has NU/LA bit set, ignore");
1155 ospf6_route_remove(old
, table
);
1160 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1161 /* To pass test suites */
1163 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
1164 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
1166 zlog_debug("Prefix has NU/LA bit set, ignore");
1168 ospf6_route_remove(old
, table
);
1172 /* Avoid infinite recursion if someone has maliciously announced
1174 Inter-Router LSA for an ABR
1176 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
1179 "Ignoring Inter-Router LSA for an ABR (%s)",
1182 ospf6_route_remove(old
, table
);
1188 /* (4) if the routing table entry for the ABR does not exist */
1189 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
1190 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
1191 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
1192 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
1193 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
1196 "%s: ABR router entry %pFX does not exist, ignore",
1197 __func__
, &abr_prefix
);
1199 if (old
->type
== OSPF6_DEST_TYPE_ROUTER
&&
1200 oa
->intra_brouter_calc
) {
1203 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1204 __func__
, buf
, (void *)old
);
1208 "%s: remove old entry: %s %p ",
1209 __func__
, buf
, (void *)old
);
1210 ospf6_abr_old_route_remove(lsa
, old
, table
);
1216 /* (5),(6): the path preference is handled by the sorting
1217 in the routing table. Always install the path by substituting
1218 old route (if any). */
1219 route
= ospf6_route_create(oa
->ospf6
);
1222 route
->prefix
= prefix
;
1223 route
->prefix_options
= prefix_options
;
1224 route
->path
.origin
.type
= lsa
->header
->type
;
1225 route
->path
.origin
.id
= lsa
->header
->id
;
1226 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1227 route
->path
.router_bits
= router_bits
;
1228 route
->path
.options
[0] = options
[0];
1229 route
->path
.options
[1] = options
[1];
1230 route
->path
.options
[2] = options
[2];
1231 route
->path
.area_id
= oa
->area_id
;
1232 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
1233 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
1235 /* copy brouter rechable nexthops into the route. */
1236 ospf6_route_copy_nexthops(route
, abr_entry
);
1238 /* (7) If the routes are identical, copy the next hops over to existing
1239 route. ospf6's route table implementation will otherwise string both
1240 routes, but keep the older one as the best route since the routes
1243 old
= ospf6_route_lookup(&prefix
, table
);
1246 zlog_debug("%s: found old route %pFX, paths %d",
1247 __func__
, &prefix
, listcount(old
->paths
));
1249 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1251 /* The route linked-list is grouped in batches of prefix.
1252 * If the new prefix is not the same as the one of interest
1253 * then we have walked over the end of the batch and so we
1254 * should break rather than continuing unnecessarily.
1256 if (!ospf6_route_is_same(old_route
, route
))
1258 if ((old_route
->type
!= route
->type
)
1259 || (old_route
->path
.type
!= route
->path
.type
))
1262 if ((ospf6_route_cmp(route
, old_route
) != 0)) {
1265 "%s: old %p %pFX cost %u new route cost %u are not same",
1266 __func__
, (void *)old_route
, &prefix
,
1267 old_route
->path
.cost
, route
->path
.cost
);
1269 /* Check new route's adv. router is same in one of
1270 * the paths with differed cost, if so remove the
1271 * old path as later new route will be added.
1273 if (listcount(old_route
->paths
) > 1)
1274 ospf6_abr_old_path_update(old_route
, route
,
1279 list_delete_all_node(old_route
->nh_list
);
1280 ospf6_route_copy_nexthops(old_route
, route
);
1281 old_entry_updated
= true;
1283 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1285 if (o_path
->area_id
== route
->path
.area_id
1286 && ospf6_ls_origin_same(o_path
, &route
->path
))
1290 /* New adv. router for a existing path add to paths list */
1291 if (o_path
== NULL
) {
1292 ecmp_path
= ospf6_path_dup(&route
->path
);
1294 /* Add a nh_list to new ecmp path */
1295 ospf6_copy_nexthops(ecmp_path
->nh_list
, route
->nh_list
);
1297 /* Add the new path to route's path list */
1298 listnode_add_sort(old_route
->paths
, ecmp_path
);
1302 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1303 __func__
, &route
->prefix
,
1304 old_route
->path
.cost
,
1305 &ecmp_path
->origin
.adv_router
,
1306 listcount(ecmp_path
->nh_list
),
1308 ? listcount(old_route
->paths
)
1310 listcount(old_route
->nh_list
));
1313 struct ospf6_route
*tmp_route
;
1315 tmp_route
= ospf6_route_create(oa
->ospf6
);
1317 ospf6_copy_nexthops(tmp_route
->nh_list
,
1320 if (ospf6_route_cmp_nexthops(tmp_route
, route
) != 0) {
1321 /* adv. router exists in the list, update nhs */
1322 list_delete_all_node(o_path
->nh_list
);
1323 ospf6_copy_nexthops(o_path
->nh_list
,
1325 ospf6_route_delete(tmp_route
);
1327 /* adv. router has no change in nhs */
1328 old_entry_updated
= false;
1329 ospf6_route_delete(tmp_route
);
1336 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1337 __func__
, buf
, (void *)old_route
,
1338 old_route
->path
.cost
, route
->path
.cost
,
1339 listcount(old_route
->nh_list
));
1341 /* For Inter-Prefix route: Update RIB/FIB,
1342 * For Inter-Router trigger summary update
1344 if (table
->hook_add
)
1345 (*table
->hook_add
)(old_route
);
1350 /* If the old entry is not updated and old entry not found or old entry
1351 * does not match with the new entry then add the new route
1353 if (old_entry_updated
== false) {
1354 if ((old
== NULL
) || (old
->type
!= route
->type
)
1355 || (old
->path
.type
!= route
->path
.type
)
1356 || (old
->path
.cost
!= route
->path
.cost
))
1363 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1364 __func__
, buf
, route
->path
.cost
,
1365 listcount(route
->nh_list
),
1366 &route
->path
.origin
.adv_router
);
1369 path
= ospf6_path_dup(&route
->path
);
1370 ospf6_copy_nexthops(path
->nh_list
, abr_entry
->nh_list
);
1371 listnode_add_sort(route
->paths
, path
);
1372 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1373 ospf6_route_add(route
, table
);
1375 /* if we did not add the route remove it */
1376 ospf6_route_delete(route
);
1379 void ospf6_abr_examin_brouter(uint32_t router_id
, struct ospf6_route
*route
,
1380 struct ospf6
*ospf6
)
1382 struct ospf6_lsa
*lsa
;
1383 struct ospf6_area
*oa
;
1386 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
1388 * It is possible to designate a non backbone
1389 * area first. If that is the case safely
1390 * fall out of this function.
1395 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
1396 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1397 ospf6_abr_examin_summary(lsa
, oa
);
1399 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
1400 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1401 ospf6_abr_examin_summary(lsa
, oa
);
1404 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
1406 struct ospf6_route
*route
;
1408 if (IS_OSPF6_DEBUG_ABR
)
1409 zlog_debug("Re-examining Inter-Prefix Summaries");
1411 for (route
= ospf6_route_head(o
->route_table
); route
;
1412 route
= ospf6_route_next(route
))
1413 ospf6_abr_originate_summary(route
, o
);
1415 if (IS_OSPF6_DEBUG_ABR
)
1416 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1420 /* Display functions */
1421 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1422 char *buf
, int buflen
,
1425 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1426 struct in6_addr in6
;
1431 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1434 ospf6_prefix_in6_addr(&in6
, prefix_lsa
, &prefix_lsa
->prefix
);
1436 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1437 snprintf(tbuf
, sizeof(tbuf
), "/%d",
1438 prefix_lsa
->prefix
.prefix_length
);
1439 strlcat(buf
, tbuf
, buflen
);
1446 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1447 struct ospf6_lsa
*lsa
,
1448 json_object
*json_obj
,
1451 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1452 char buf
[INET6_ADDRSTRLEN
];
1454 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1458 json_object_int_add(
1460 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1461 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1463 json_object_string_add(json_obj
, "prefixOptions", buf
);
1464 json_object_string_add(
1466 ospf6_inter_area_prefix_lsa_get_prefix_str(
1467 lsa
, buf
, sizeof(buf
), 0));
1469 vty_out(vty
, " Metric: %lu\n",
1470 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1472 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1474 vty_out(vty
, " Prefix Options: %s\n", buf
);
1476 vty_out(vty
, " Prefix: %s\n",
1477 ospf6_inter_area_prefix_lsa_get_prefix_str(
1478 lsa
, buf
, sizeof(buf
), 0));
1484 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1485 char *buf
, int buflen
,
1488 struct ospf6_inter_router_lsa
*router_lsa
;
1492 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1497 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1503 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1504 struct ospf6_lsa
*lsa
,
1505 json_object
*json_obj
,
1508 struct ospf6_inter_router_lsa
*router_lsa
;
1511 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1514 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1516 json_object_string_add(json_obj
, "options", buf
);
1517 json_object_int_add(
1519 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1521 vty_out(vty
, " Options: %s\n", buf
);
1522 vty_out(vty
, " Metric: %lu\n",
1523 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1526 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1528 json_object_string_add(json_obj
, "destinationRouterId", buf
);
1530 vty_out(vty
, " Destination Router ID: %s\n", buf
);
1535 /* Debug commands */
1536 DEFUN (debug_ospf6_abr
,
1537 debug_ospf6_abr_cmd
,
1541 "Debug OSPFv3 ABR function\n"
1544 OSPF6_DEBUG_ABR_ON();
1548 DEFUN (no_debug_ospf6_abr
,
1549 no_debug_ospf6_abr_cmd
,
1550 "no debug ospf6 abr",
1554 "Debug OSPFv3 ABR function\n"
1557 OSPF6_DEBUG_ABR_OFF();
1561 int config_write_ospf6_debug_abr(struct vty
*vty
)
1563 if (IS_OSPF6_DEBUG_ABR
)
1564 vty_out(vty
, "debug ospf6 abr\n");
1568 void install_element_ospf6_debug_abr(void)
1570 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1571 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1572 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1573 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1576 static struct ospf6_lsa_handler inter_prefix_handler
= {
1577 .lh_type
= OSPF6_LSTYPE_INTER_PREFIX
,
1578 .lh_name
= "Inter-Prefix",
1579 .lh_short_name
= "IAP",
1580 .lh_show
= ospf6_inter_area_prefix_lsa_show
,
1581 .lh_get_prefix_str
= ospf6_inter_area_prefix_lsa_get_prefix_str
,
1584 static struct ospf6_lsa_handler inter_router_handler
= {
1585 .lh_type
= OSPF6_LSTYPE_INTER_ROUTER
,
1586 .lh_name
= "Inter-Router",
1587 .lh_short_name
= "IAR",
1588 .lh_show
= ospf6_inter_area_router_lsa_show
,
1589 .lh_get_prefix_str
= ospf6_inter_area_router_lsa_get_prefix_str
,
1592 void ospf6_abr_init(void)
1594 ospf6_install_lsa_handler(&inter_prefix_handler
);
1595 ospf6_install_lsa_handler(&inter_router_handler
);