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 summary
->path
.origin
.type
=
519 htons(OSPF6_LSTYPE_INTER_PREFIX
);
520 summary
->path
.origin
.id
= ospf6_new_ls_id(
521 summary
->path
.origin
.type
,
522 summary
->path
.origin
.adv_router
, area
->lsdb
);
524 summary
= ospf6_route_add(summary
, summary_table
);
526 summary
->type
= route
->type
;
527 monotime(&summary
->changed
);
530 summary
->prefix_options
= route
->prefix_options
;
531 summary
->path
.router_bits
= route
->path
.router_bits
;
532 summary
->path
.options
[0] = route
->path
.options
[0];
533 summary
->path
.options
[1] = route
->path
.options
[1];
534 summary
->path
.options
[2] = route
->path
.options
[2];
535 summary
->path
.area_id
= area
->area_id
;
536 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
537 summary
->path
.subtype
= route
->path
.subtype
;
538 summary
->path
.cost
= route
->path
.cost
;
539 /* summary->nexthop[0] = route->nexthop[0]; */
542 memset(buffer
, 0, sizeof(buffer
));
543 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
545 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
546 router_lsa
= (struct ospf6_inter_router_lsa
547 *)((caddr_t
)lsa_header
548 + sizeof(struct ospf6_lsa_header
));
549 p
= (caddr_t
)router_lsa
+ sizeof(struct ospf6_inter_router_lsa
);
551 /* Fill Inter-Area-Router-LSA */
552 router_lsa
->options
[0] = route
->path
.options
[0];
553 router_lsa
->options
[1] = route
->path
.options
[1];
554 router_lsa
->options
[2] = route
->path
.options
[2];
555 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa
, route
->path
.cost
);
556 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX(&route
->prefix
);
557 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
559 prefix_lsa
= (struct ospf6_inter_prefix_lsa
560 *)((caddr_t
)lsa_header
561 + sizeof(struct ospf6_lsa_header
));
562 p
= (caddr_t
)prefix_lsa
+ sizeof(struct ospf6_inter_prefix_lsa
);
564 /* Fill Inter-Area-Prefix-LSA */
565 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa
, route
->path
.cost
);
566 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
567 prefix_lsa
->prefix
.prefix_options
= route
->prefix_options
;
570 memcpy(p
, &route
->prefix
.u
.prefix6
,
571 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
572 ospf6_prefix_apply_mask(&prefix_lsa
->prefix
);
573 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
574 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
577 /* Fill LSA Header */
579 lsa_header
->type
= type
;
580 lsa_header
->id
= summary
->path
.origin
.id
;
581 lsa_header
->adv_router
= area
->ospf6
->router_id
;
583 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
584 lsa_header
->adv_router
, area
->lsdb
);
585 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
588 ospf6_lsa_checksum(lsa_header
);
591 lsa
= ospf6_lsa_create(lsa_header
);
593 /* Reset the unapproved flag */
594 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
597 ospf6_lsa_originate_area(lsa
, area
);
599 if (IS_OSPF6_DEBUG_ABR
)
600 zlog_debug("%s : finish area %s", __func__
, area
->name
);
605 void ospf6_abr_range_reset_cost(struct ospf6
*ospf6
)
607 struct listnode
*node
, *nnode
;
608 struct ospf6_area
*oa
;
609 struct ospf6_route
*range
;
611 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
612 for (range
= ospf6_route_head(oa
->range_table
); range
;
613 range
= ospf6_route_next(range
))
614 OSPF6_ABR_RANGE_CLEAR_COST(range
);
615 for (range
= ospf6_route_head(oa
->nssa_range_table
); range
;
616 range
= ospf6_route_next(range
))
617 OSPF6_ABR_RANGE_CLEAR_COST(range
);
621 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route
*range
,
624 struct ospf6_route
*ro
;
627 for (ro
= ospf6_route_match_head(&range
->prefix
, o
->route_table
); ro
;
628 ro
= ospf6_route_match_next(&range
->prefix
, ro
)) {
629 if (CHECK_FLAG(ro
->flag
, OSPF6_ROUTE_REMOVE
))
631 if (ro
->path
.area_id
!= range
->path
.area_id
)
633 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
634 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL1
635 && ro
->path
.type
!= OSPF6_PATH_TYPE_EXTERNAL2
)
637 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)
638 && ro
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
641 cost
= MAX(cost
, ro
->path
.cost
);
648 ospf6_abr_range_summary_needs_update(struct ospf6_route
*range
, uint32_t cost
)
650 int redo_summary
= 0;
652 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
653 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
655 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
656 if (range
->path
.cost
!= 0) {
657 range
->path
.cost
= 0;
661 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
662 && range
->path
.cost
!= range
->path
.u
.cost_config
)) {
663 range
->path
.cost
= range
->path
.u
.cost_config
;
664 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
666 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
667 && range
->path
.cost
!= cost
) {
668 range
->path
.cost
= cost
;
669 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
672 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
673 /* Cost is zero, meaning no active range */
674 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
675 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
679 return (redo_summary
);
682 void ospf6_abr_range_update(struct ospf6_route
*range
, struct ospf6
*ospf6
)
685 struct listnode
*node
, *nnode
;
686 struct ospf6_area
*oa
;
687 int summary_orig
= 0;
689 assert(range
->type
== OSPF6_DEST_TYPE_RANGE
);
690 oa
= ospf6_area_lookup(range
->path
.area_id
, ospf6
);
693 /* update range's cost and active flag */
694 cost
= ospf6_abr_range_compute_cost(range
, ospf6
);
696 if (IS_OSPF6_DEBUG_ABR
)
697 zlog_debug("%s: range %pFX, cost %d", __func__
, &range
->prefix
,
700 /* Non-zero cost is a proxy for active longer prefixes in this range.
701 * If there are active routes covered by this range AND either the
703 * cost has changed or the summarized cost has changed then redo
705 * Alternately, if there are no longer active prefixes and there are
706 * summary announcements, withdraw those announcements.
708 * The don't advertise code relies on the path.cost being set to UNSPEC
710 * work the first time. Subsequent times the path.cost is not 0 anyway
712 * were active ranges.
714 if (!ospf6_abr_range_summary_needs_update(range
, cost
))
717 if (IS_OSPF6_DEBUG_ABR
)
718 zlog_debug("%s: range %pFX update", __func__
, &range
->prefix
);
720 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
)) {
721 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
722 && !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
723 ospf6_nssa_lsa_originate(range
, oa
, true);
726 struct ospf6_lsa
*lsa
;
728 lsa
= ospf6_lsdb_lookup(range
->path
.origin
.type
,
729 range
->path
.origin
.id
,
730 ospf6
->router_id
, oa
->lsdb
);
732 ospf6_lsa_premature_aging(lsa
);
735 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
737 ospf6_abr_originate_summary_to_area(range
, oa
);
741 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
743 if (!CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
744 if (IS_OSPF6_DEBUG_ABR
)
745 zlog_debug("Add discard route");
747 ospf6_zebra_add_discard(range
, ospf6
);
750 /* Summary removed or no summary generated as no
752 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
753 if (IS_OSPF6_DEBUG_ABR
)
754 zlog_debug("Delete discard route");
756 ospf6_zebra_delete_discard(range
, ospf6
);
761 void ospf6_abr_originate_summary(struct ospf6_route
*route
, struct ospf6
*ospf6
)
763 struct listnode
*node
, *nnode
;
764 struct ospf6_area
*oa
;
765 struct ospf6_route
*range
= NULL
;
767 if (IS_OSPF6_DEBUG_ABR
) {
770 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
772 &ADV_ROUTER_IN_PREFIX(&route
->prefix
), buf
,
775 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
777 zlog_debug("%s: route %s", __func__
, buf
);
780 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
781 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
783 zlog_err("OSPFv6 area lookup failed");
787 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
790 ospf6_abr_range_update(range
, ospf6
);
794 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
795 ospf6_abr_originate_summary_to_area(route
, oa
);
798 void ospf6_abr_defaults_to_stub(struct ospf6
*o
)
800 struct listnode
*node
, *nnode
;
801 struct ospf6_area
*oa
;
802 struct ospf6_route
*def
, *route
;
803 int type
= DEFAULT_ROUTE
;
808 def
= ospf6_route_create(o
);
809 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
810 def
->prefix
.family
= AF_INET6
;
811 def
->prefix
.prefixlen
= 0;
812 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
813 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
814 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
815 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
816 def
->path
.area_id
= o
->backbone
->area_id
;
817 def
->path
.metric_type
= metric_type(o
, type
, 0);
818 def
->path
.cost
= metric_value(o
, type
, 0);
820 for (ALL_LIST_ELEMENTS(o
->area_list
, node
, nnode
, oa
)) {
821 if (IS_AREA_STUB(oa
) || (IS_AREA_NSSA(oa
) && oa
->no_summary
)) {
822 /* announce defaults to stubby areas */
823 if (IS_OSPF6_DEBUG_ABR
)
825 "Announcing default route into stubby area %s",
827 UNSET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
828 ospf6_abr_originate_summary_to_area(def
, oa
);
830 /* withdraw defaults when an area switches from stub to
832 route
= ospf6_route_lookup(&def
->prefix
,
835 && (route
->path
.subtype
== def
->path
.subtype
)) {
836 if (IS_OSPF6_DEBUG_ABR
)
838 "Withdrawing default route from non-stubby area %s",
840 SET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
841 ospf6_abr_originate_summary_to_area(def
, oa
);
845 ospf6_route_delete(def
);
848 void ospf6_abr_old_path_update(struct ospf6_route
*old_route
,
849 struct ospf6_route
*route
,
850 struct ospf6_route_table
*table
)
852 struct ospf6_path
*o_path
= NULL
;
853 struct listnode
*anode
, *anext
;
854 struct listnode
*nnode
, *rnode
, *rnext
;
855 struct ospf6_nexthop
*nh
, *rnh
;
857 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
, o_path
)) {
858 if (o_path
->area_id
!= route
->path
.area_id
859 || !ospf6_ls_origin_same(o_path
, &route
->path
))
862 if ((o_path
->cost
== route
->path
.cost
) &&
863 (o_path
->u
.cost_e2
== route
->path
.u
.cost_e2
))
866 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
867 for (ALL_LIST_ELEMENTS(old_route
->nh_list
, rnode
,
869 if (!ospf6_nexthop_is_same(rnh
, nh
))
871 listnode_delete(old_route
->nh_list
, rnh
);
872 ospf6_nexthop_delete(rnh
);
877 listnode_delete(old_route
->paths
, o_path
);
878 ospf6_path_free(o_path
);
880 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
,
882 ospf6_merge_nexthops(old_route
->nh_list
,
886 if (IS_OSPF6_DEBUG_ABR
|| IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
887 zlog_debug("%s: paths %u nh %u", __func__
,
889 ? listcount(old_route
->paths
)
892 ? listcount(old_route
->nh_list
)
896 (*table
->hook_add
)(old_route
);
898 if (old_route
->path
.origin
.id
== route
->path
.origin
.id
&&
899 old_route
->path
.origin
.adv_router
==
900 route
->path
.origin
.adv_router
) {
901 struct ospf6_path
*h_path
;
903 h_path
= (struct ospf6_path
*)
904 listgetdata(listhead(old_route
->paths
));
905 old_route
->path
.origin
.type
= h_path
->origin
.type
;
906 old_route
->path
.origin
.id
= h_path
->origin
.id
;
907 old_route
->path
.origin
.adv_router
=
908 h_path
->origin
.adv_router
;
913 void ospf6_abr_old_route_remove(struct ospf6_lsa
*lsa
, struct ospf6_route
*old
,
914 struct ospf6_route_table
*table
)
916 if (IS_OSPF6_DEBUG_ABR
)
917 zlog_debug("%s: route %pFX, paths %d", __func__
, &old
->prefix
,
918 listcount(old
->paths
));
920 if (listcount(old
->paths
) > 1) {
921 struct listnode
*anode
, *anext
, *nnode
, *rnode
, *rnext
;
922 struct ospf6_path
*o_path
;
923 struct ospf6_nexthop
*nh
, *rnh
;
924 bool nh_updated
= false;
926 for (ALL_LIST_ELEMENTS(old
->paths
, anode
, anext
, o_path
)) {
927 if (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
928 || o_path
->origin
.id
!= lsa
->header
->id
)
930 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
931 for (ALL_LIST_ELEMENTS(old
->nh_list
,
932 rnode
, rnext
, rnh
)) {
933 if (!ospf6_nexthop_is_same(rnh
, nh
))
935 if (IS_OSPF6_DEBUG_ABR
)
936 zlog_debug("deleted nexthop");
937 listnode_delete(old
->nh_list
, rnh
);
938 ospf6_nexthop_delete(rnh
);
941 listnode_delete(old
->paths
, o_path
);
942 ospf6_path_free(o_path
);
947 if (listcount(old
->paths
)) {
948 if (IS_OSPF6_DEBUG_ABR
949 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
))
950 zlog_debug("%s: old %pFX updated nh %u",
951 __func__
, &old
->prefix
,
952 old
->nh_list
? listcount(
957 (*table
->hook_add
)(old
);
959 if ((old
->path
.origin
.id
== lsa
->header
->id
) &&
960 (old
->path
.origin
.adv_router
961 == lsa
->header
->adv_router
)) {
962 struct ospf6_path
*h_path
;
964 h_path
= (struct ospf6_path
*)
966 listhead(old
->paths
));
967 old
->path
.origin
.type
=
969 old
->path
.origin
.id
= h_path
->origin
.id
;
970 old
->path
.origin
.adv_router
=
971 h_path
->origin
.adv_router
;
974 ospf6_route_remove(old
, table
);
977 ospf6_route_remove(old
, table
);
980 /* RFC 2328 16.2. Calculating the inter-area routes */
981 void ospf6_abr_examin_summary(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
983 struct prefix prefix
, abr_prefix
;
984 struct ospf6_route_table
*table
= NULL
;
985 struct ospf6_route
*range
, *route
, *old
= NULL
, *old_route
;
986 struct ospf6_route
*abr_entry
;
988 char options
[3] = {0, 0, 0};
989 uint8_t prefix_options
= 0;
991 uint8_t router_bits
= 0;
992 char buf
[PREFIX2STR_BUFFER
];
994 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
995 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
996 bool old_entry_updated
= false;
997 struct ospf6_path
*path
, *o_path
, *ecmp_path
;
998 struct listnode
*anode
;
999 bool add_route
= false;
1001 memset(&prefix
, 0, sizeof(prefix
));
1003 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1004 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
)) {
1006 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1007 lsa
->name
, ospf6_lsa_age_current(lsa
),
1012 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1014 prefix
.family
= AF_INET6
;
1015 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
1016 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, prefix_lsa
,
1017 &prefix_lsa
->prefix
);
1019 prefix2str(&prefix
, buf
, sizeof(buf
));
1020 table
= oa
->ospf6
->route_table
;
1021 type
= OSPF6_DEST_TYPE_NETWORK
;
1022 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
1023 cost
= OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
);
1024 } else if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1025 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER
)) {
1027 zlog_debug("%s: LSA %s age %d in area %s", __func__
,
1028 lsa
->name
, ospf6_lsa_age_current(lsa
),
1033 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1035 ospf6_linkstate_prefix(router_lsa
->router_id
, htonl(0),
1038 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
,
1041 table
= oa
->ospf6
->brouter_table
;
1042 type
= OSPF6_DEST_TYPE_ROUTER
;
1043 options
[0] = router_lsa
->options
[0];
1044 options
[1] = router_lsa
->options
[1];
1045 options
[2] = router_lsa
->options
[2];
1046 cost
= OSPF6_ABR_SUMMARY_METRIC(router_lsa
);
1047 SET_FLAG(router_bits
, OSPF6_ROUTER_BIT_E
);
1051 /* Find existing route */
1052 route
= ospf6_route_lookup(&prefix
, table
);
1054 ospf6_route_lock(route
);
1056 zlog_debug("%s: route %pFX, paths %d", __func__
,
1057 &prefix
, listcount(route
->paths
));
1059 while (route
&& ospf6_route_is_prefix(&prefix
, route
)) {
1060 if (route
->path
.area_id
== oa
->area_id
1061 && route
->path
.origin
.type
== lsa
->header
->type
1062 && !CHECK_FLAG(route
->flag
, OSPF6_ROUTE_WAS_REMOVED
)) {
1063 /* LSA adv. router could be part of route's
1064 * paths list. Find the existing path and set
1067 if (listcount(route
->paths
) > 1) {
1068 for (ALL_LIST_ELEMENTS_RO(route
->paths
, anode
,
1070 if (o_path
->origin
.id
== lsa
->header
->id
1071 && o_path
->origin
.adv_router
==
1072 lsa
->header
->adv_router
) {
1077 "%s: old entry found in paths, adv_router %pI4",
1079 &o_path
->origin
.adv_router
);
1084 } else if (route
->path
.origin
.id
== lsa
->header
->id
&&
1085 route
->path
.origin
.adv_router
==
1086 lsa
->header
->adv_router
)
1089 route
= ospf6_route_next(route
);
1092 ospf6_route_unlock(route
);
1094 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1095 if (cost
== OSPF_LS_INFINITY
) {
1097 zlog_debug("cost is LS_INFINITY, ignore");
1099 ospf6_abr_old_route_remove(lsa
, old
, table
);
1102 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
1104 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__
,
1107 ospf6_abr_old_route_remove(lsa
, old
, table
);
1112 /* (2) if the LSA is self-originated, ignore */
1113 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
1115 zlog_debug("LSA %s is self-originated, ignore",
1118 ospf6_route_remove(old
, table
);
1122 /* (3) if the prefix is equal to an active configured address range */
1123 /* or if the NU bit is set in the prefix */
1124 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
1125 /* must have been set in previous block */
1128 range
= ospf6_route_lookup(&prefix
, oa
->range_table
);
1132 "Prefix is equal to address range, ignore");
1134 ospf6_route_remove(old
, table
);
1138 if (CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
1139 OSPF6_PREFIX_OPTION_NU
)) {
1141 zlog_debug("Prefix has the NU bit set, ignore");
1143 ospf6_route_remove(old
, table
);
1148 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
1149 /* To pass test suites */
1151 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
1152 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
1155 "Router-LSA has the V6-bit or R-bit unset, ignore");
1157 ospf6_route_remove(old
, table
);
1161 /* Avoid infinite recursion if someone has maliciously announced
1163 Inter-Router LSA for an ABR
1165 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
1168 "Ignoring Inter-Router LSA for an ABR (%s)",
1171 ospf6_route_remove(old
, table
);
1177 /* (4) if the routing table entry for the ABR does not exist */
1178 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
1179 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
1180 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
1181 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
1182 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
1185 "%s: ABR router entry %pFX does not exist, ignore",
1186 __func__
, &abr_prefix
);
1188 if (old
->type
== OSPF6_DEST_TYPE_ROUTER
&&
1189 oa
->intra_brouter_calc
) {
1192 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1193 __func__
, buf
, (void *)old
);
1197 "%s: remove old entry: %s %p ",
1198 __func__
, buf
, (void *)old
);
1199 ospf6_abr_old_route_remove(lsa
, old
, table
);
1205 /* (5),(6): the path preference is handled by the sorting
1206 in the routing table. Always install the path by substituting
1207 old route (if any). */
1208 route
= ospf6_route_create(oa
->ospf6
);
1211 route
->prefix
= prefix
;
1212 route
->prefix_options
= prefix_options
;
1213 route
->path
.origin
.type
= lsa
->header
->type
;
1214 route
->path
.origin
.id
= lsa
->header
->id
;
1215 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1216 route
->path
.router_bits
= router_bits
;
1217 route
->path
.options
[0] = options
[0];
1218 route
->path
.options
[1] = options
[1];
1219 route
->path
.options
[2] = options
[2];
1220 route
->path
.area_id
= oa
->area_id
;
1221 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
1222 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
1224 /* copy brouter rechable nexthops into the route. */
1225 ospf6_route_copy_nexthops(route
, abr_entry
);
1227 /* (7) If the routes are identical, copy the next hops over to existing
1228 route. ospf6's route table implementation will otherwise string both
1229 routes, but keep the older one as the best route since the routes
1232 old
= ospf6_route_lookup(&prefix
, table
);
1235 zlog_debug("%s: found old route %pFX, paths %d",
1236 __func__
, &prefix
, listcount(old
->paths
));
1238 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1240 /* The route linked-list is grouped in batches of prefix.
1241 * If the new prefix is not the same as the one of interest
1242 * then we have walked over the end of the batch and so we
1243 * should break rather than continuing unnecessarily.
1245 if (!ospf6_route_is_same(old_route
, route
))
1247 if ((old_route
->type
!= route
->type
)
1248 || (old_route
->path
.type
!= route
->path
.type
))
1251 if ((ospf6_route_cmp(route
, old_route
) != 0)) {
1254 "%s: old %p %pFX cost %u new route cost %u are not same",
1255 __func__
, (void *)old_route
, &prefix
,
1256 old_route
->path
.cost
, route
->path
.cost
);
1258 /* Check new route's adv. router is same in one of
1259 * the paths with differed cost, if so remove the
1260 * old path as later new route will be added.
1262 if (listcount(old_route
->paths
) > 1)
1263 ospf6_abr_old_path_update(old_route
, route
,
1268 list_delete_all_node(old_route
->nh_list
);
1269 ospf6_route_copy_nexthops(old_route
, route
);
1270 old_entry_updated
= true;
1272 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1274 if (o_path
->area_id
== route
->path
.area_id
1275 && ospf6_ls_origin_same(o_path
, &route
->path
))
1279 /* New adv. router for a existing path add to paths list */
1280 if (o_path
== NULL
) {
1281 ecmp_path
= ospf6_path_dup(&route
->path
);
1283 /* Add a nh_list to new ecmp path */
1284 ospf6_copy_nexthops(ecmp_path
->nh_list
, route
->nh_list
);
1286 /* Add the new path to route's path list */
1287 listnode_add_sort(old_route
->paths
, ecmp_path
);
1291 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1292 __func__
, &route
->prefix
,
1293 old_route
->path
.cost
,
1294 &ecmp_path
->origin
.adv_router
,
1295 listcount(ecmp_path
->nh_list
),
1297 ? listcount(old_route
->paths
)
1299 listcount(old_route
->nh_list
));
1302 struct ospf6_route
*tmp_route
;
1304 tmp_route
= ospf6_route_create(oa
->ospf6
);
1306 ospf6_copy_nexthops(tmp_route
->nh_list
,
1309 if (!ospf6_route_cmp_nexthops(tmp_route
, route
)) {
1310 /* adv. router exists in the list, update nhs */
1311 list_delete_all_node(o_path
->nh_list
);
1312 ospf6_copy_nexthops(o_path
->nh_list
,
1314 ospf6_route_delete(tmp_route
);
1316 /* adv. router has no change in nhs */
1317 old_entry_updated
= false;
1318 ospf6_route_delete(tmp_route
);
1325 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1326 __func__
, buf
, (void *)old_route
,
1327 old_route
->path
.cost
, route
->path
.cost
,
1328 listcount(old_route
->nh_list
));
1330 /* For Inter-Prefix route: Update RIB/FIB,
1331 * For Inter-Router trigger summary update
1333 if (table
->hook_add
)
1334 (*table
->hook_add
)(old_route
);
1339 /* If the old entry is not updated and old entry not found or old entry
1340 * does not match with the new entry then add the new route
1342 if (old_entry_updated
== false) {
1343 if ((old
== NULL
) || (old
->type
!= route
->type
)
1344 || (old
->path
.type
!= route
->path
.type
)
1345 || (old
->path
.cost
!= route
->path
.cost
))
1352 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1353 __func__
, buf
, route
->path
.cost
,
1354 listcount(route
->nh_list
),
1355 &route
->path
.origin
.adv_router
);
1358 path
= ospf6_path_dup(&route
->path
);
1359 ospf6_copy_nexthops(path
->nh_list
, abr_entry
->nh_list
);
1360 listnode_add_sort(route
->paths
, path
);
1361 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1362 ospf6_route_add(route
, table
);
1364 /* if we did not add the route remove it */
1365 ospf6_route_delete(route
);
1368 void ospf6_abr_examin_brouter(uint32_t router_id
, struct ospf6_route
*route
,
1369 struct ospf6
*ospf6
)
1371 struct ospf6_lsa
*lsa
;
1372 struct ospf6_area
*oa
;
1375 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
1377 * It is possible to designate a non backbone
1378 * area first. If that is the case safely
1379 * fall out of this function.
1384 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
1385 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1386 ospf6_abr_examin_summary(lsa
, oa
);
1388 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
1389 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
1390 ospf6_abr_examin_summary(lsa
, oa
);
1393 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
1395 struct ospf6_route
*route
;
1397 if (IS_OSPF6_DEBUG_ABR
)
1398 zlog_debug("Re-examining Inter-Prefix Summaries");
1400 for (route
= ospf6_route_head(o
->route_table
); route
;
1401 route
= ospf6_route_next(route
))
1402 ospf6_abr_originate_summary(route
, o
);
1404 if (IS_OSPF6_DEBUG_ABR
)
1405 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1409 /* Display functions */
1410 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1411 char *buf
, int buflen
,
1414 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1415 struct in6_addr in6
;
1420 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1423 ospf6_prefix_in6_addr(&in6
, prefix_lsa
, &prefix_lsa
->prefix
);
1425 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1426 snprintf(tbuf
, sizeof(tbuf
), "/%d",
1427 prefix_lsa
->prefix
.prefix_length
);
1428 strlcat(buf
, tbuf
, buflen
);
1435 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1436 struct ospf6_lsa
*lsa
,
1437 json_object
*json_obj
,
1440 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1441 char buf
[INET6_ADDRSTRLEN
];
1443 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1447 json_object_int_add(
1449 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1450 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1452 json_object_string_add(json_obj
, "prefixOptions", buf
);
1453 json_object_string_add(
1455 ospf6_inter_area_prefix_lsa_get_prefix_str(
1456 lsa
, buf
, sizeof(buf
), 0));
1458 vty_out(vty
, " Metric: %lu\n",
1459 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1461 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
,
1463 vty_out(vty
, " Prefix Options: %s\n", buf
);
1465 vty_out(vty
, " Prefix: %s\n",
1466 ospf6_inter_area_prefix_lsa_get_prefix_str(
1467 lsa
, buf
, sizeof(buf
), 0));
1473 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1474 char *buf
, int buflen
,
1477 struct ospf6_inter_router_lsa
*router_lsa
;
1481 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1486 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1492 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1493 struct ospf6_lsa
*lsa
,
1494 json_object
*json_obj
,
1497 struct ospf6_inter_router_lsa
*router_lsa
;
1500 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1503 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1505 json_object_string_add(json_obj
, "options", buf
);
1506 json_object_int_add(
1508 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1510 vty_out(vty
, " Options: %s\n", buf
);
1511 vty_out(vty
, " Metric: %lu\n",
1512 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1515 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1517 json_object_string_add(json_obj
, "destinationRouterId", buf
);
1519 vty_out(vty
, " Destination Router ID: %s\n", buf
);
1524 /* Debug commands */
1525 DEFUN (debug_ospf6_abr
,
1526 debug_ospf6_abr_cmd
,
1530 "Debug OSPFv3 ABR function\n"
1533 OSPF6_DEBUG_ABR_ON();
1537 DEFUN (no_debug_ospf6_abr
,
1538 no_debug_ospf6_abr_cmd
,
1539 "no debug ospf6 abr",
1543 "Debug OSPFv3 ABR function\n"
1546 OSPF6_DEBUG_ABR_OFF();
1550 int config_write_ospf6_debug_abr(struct vty
*vty
)
1552 if (IS_OSPF6_DEBUG_ABR
)
1553 vty_out(vty
, "debug ospf6 abr\n");
1557 void install_element_ospf6_debug_abr(void)
1559 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1560 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1561 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1562 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1565 static struct ospf6_lsa_handler inter_prefix_handler
= {
1566 .lh_type
= OSPF6_LSTYPE_INTER_PREFIX
,
1567 .lh_name
= "Inter-Prefix",
1568 .lh_short_name
= "IAP",
1569 .lh_show
= ospf6_inter_area_prefix_lsa_show
,
1570 .lh_get_prefix_str
= ospf6_inter_area_prefix_lsa_get_prefix_str
,
1573 static struct ospf6_lsa_handler inter_router_handler
= {
1574 .lh_type
= OSPF6_LSTYPE_INTER_ROUTER
,
1575 .lh_name
= "Inter-Router",
1576 .lh_short_name
= "IAR",
1577 .lh_show
= ospf6_inter_area_router_lsa_show
,
1578 .lh_get_prefix_str
= ospf6_inter_area_router_lsa_get_prefix_str
,
1581 void ospf6_abr_init(void)
1583 ospf6_install_lsa_handler(&inter_prefix_handler
);
1584 ospf6_install_lsa_handler(&inter_router_handler
);