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_abr.h"
52 unsigned char conf_debug_ospf6_abr
;
54 int ospf6_is_router_abr(struct ospf6
*o
)
56 struct listnode
*node
;
57 struct ospf6_area
*oa
;
60 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, node
, oa
))
61 if (IS_AREA_ENABLED(oa
))
69 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route
*route
,
70 struct ospf6_area
*area
)
72 struct ospf6_interface
*oi
;
74 oi
= ospf6_interface_lookup_by_ifindex(
75 ospf6_route_get_first_nh_index(route
));
76 if (oi
&& oi
->area
&& oi
->area
== area
)
82 static void ospf6_abr_delete_route(struct ospf6_route
*range
,
83 struct ospf6_route
*summary
,
84 struct ospf6_route_table
*summary_table
,
85 struct ospf6_lsa
*old
)
88 ospf6_route_remove(summary
, summary_table
);
91 if (old
&& !OSPF6_LSA_IS_MAXAGE(old
))
95 void ospf6_abr_enable_area(struct ospf6_area
*area
)
97 struct ospf6_area
*oa
;
98 struct listnode
*node
, *nnode
;
100 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
101 /* update B bit for each area */
102 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
105 void ospf6_abr_disable_area(struct ospf6_area
*area
)
107 struct ospf6_area
*oa
;
108 struct ospf6_route
*ro
, *nro
;
109 struct ospf6_lsa
*old
;
110 struct listnode
*node
, *nnode
;
112 /* Withdraw all summary prefixes previously originated */
113 for (ro
= ospf6_route_head(area
->summary_prefix
); ro
; ro
= nro
) {
114 nro
= ospf6_route_next(ro
);
115 old
= ospf6_lsdb_lookup(ro
->path
.origin
.type
,
117 area
->ospf6
->router_id
, area
->lsdb
);
119 ospf6_lsa_purge(old
);
120 ospf6_route_remove(ro
, area
->summary_prefix
);
123 /* Withdraw all summary router-routes previously originated */
124 for (ro
= ospf6_route_head(area
->summary_router
); 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_router
);
134 /* Schedule Router-LSA for each area (ABR status may change) */
135 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
136 /* update B bit for each area */
137 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
140 /* RFC 2328 12.4.3. Summary-LSAs */
141 /* Returns 1 if a summary LSA has been generated for the area */
142 /* This is used by the area/range logic to add/remove blackhole routes */
143 int ospf6_abr_originate_summary_to_area(struct ospf6_route
*route
,
144 struct ospf6_area
*area
)
146 struct ospf6_lsa
*lsa
, *old
= NULL
;
147 struct ospf6_route
*summary
, *range
= NULL
;
148 struct ospf6_area
*route_area
;
149 char buffer
[OSPF6_MAX_LSASIZE
];
150 struct ospf6_lsa_header
*lsa_header
;
152 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
153 struct ospf6_inter_router_lsa
*router_lsa
;
154 struct ospf6_route_table
*summary_table
= NULL
;
156 char buf
[PREFIX2STR_BUFFER
];
159 /* Only destination type network, range or ASBR are considered */
160 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
161 && route
->type
!= OSPF6_DEST_TYPE_RANGE
162 && ((route
->type
!= OSPF6_DEST_TYPE_ROUTER
)
163 || !CHECK_FLAG(route
->path
.router_bits
, OSPF6_ROUTER_BIT_E
))) {
166 "Route type is none of network, range nor ASBR, ignore");
170 /* AS External routes are never considered */
171 if (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
172 || route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
) {
174 zlog_debug("Path type is external, skip");
178 /* do not generate if the path's area is the same as target area */
179 if (route
->path
.area_id
== area
->area_id
) {
181 zlog_debug("The route is in the area itself, ignore");
185 /* do not generate if the nexthops belongs to the target area */
186 if (ospf6_abr_nexthops_belong_to_area(route
, area
)) {
189 "The route's nexthop is in the same area, ignore");
193 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
194 if (ADV_ROUTER_IN_PREFIX(&route
->prefix
)
195 == area
->ospf6
->router_id
) {
197 &(ADV_ROUTER_IN_PREFIX(&route
->prefix
)), buf
,
200 "%s: Skipping ASBR announcement for ABR (%s)",
206 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
207 if (IS_OSPF6_DEBUG_ABR
208 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER
)) {
211 &(ADV_ROUTER_IN_PREFIX(&route
->prefix
)), buf
,
213 zlog_debug("Originating summary in area %s for ASBR %s",
216 summary_table
= area
->summary_router
;
218 if (IS_OSPF6_DEBUG_ABR
219 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX
)) {
221 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
222 zlog_debug("Originating summary in area %s for %s",
225 summary_table
= area
->summary_prefix
;
228 summary
= ospf6_route_lookup(&route
->prefix
, summary_table
);
230 old
= ospf6_lsdb_lookup(summary
->path
.origin
.type
,
231 summary
->path
.origin
.id
,
232 area
->ospf6
->router_id
, area
->lsdb
);
234 /* if this route has just removed, remove corresponding LSA */
235 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)) {
238 "The route has just removed, purge previous LSA");
240 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
241 /* Whether the route have active longer prefix */
242 if (!CHECK_FLAG(route
->flag
,
243 OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
246 "The range is not active. withdraw");
248 ospf6_abr_delete_route(route
, summary
,
252 ospf6_lsa_purge(old
);
257 if ((route
->type
== OSPF6_DEST_TYPE_ROUTER
) && IS_AREA_STUB(area
)) {
260 "Area has been stubbed, purge Inter-Router LSA");
262 ospf6_abr_delete_route(route
, summary
, summary_table
, old
);
267 && (route
->path
.subtype
!= OSPF6_PATH_SUBTYPE_DEFAULT_RT
)) {
269 zlog_debug("Area has been stubbed, purge prefix LSA");
271 ospf6_abr_delete_route(route
, summary
, summary_table
, old
);
275 /* do not generate if the route cost is greater or equal to LSInfinity
277 if (route
->path
.cost
>= OSPF_LS_INFINITY
) {
278 /* When we're clearing the range route because all active
280 * under the range are gone, we set the range's cost to
281 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
282 * don't want to trigger the code here for that. This code is
284 * handling routes that have gone to infinity. The range removal
288 if ((route
->type
!= OSPF6_DEST_TYPE_RANGE
)
289 && (route
->path
.cost
!= OSPF_AREA_RANGE_COST_UNSPEC
)) {
292 "The cost exceeds LSInfinity, withdraw");
294 ospf6_lsa_purge(old
);
299 /* if this is a route to ASBR */
300 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
301 /* Only the prefered best path is considered */
302 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
305 "This is the secondary path to the ASBR, ignore");
306 ospf6_abr_delete_route(route
, summary
, summary_table
,
311 /* Do not generate if the area is stub */
315 /* if this is an intra-area route, this may be suppressed by aggregation
317 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
318 && route
->path
.type
== OSPF6_PATH_TYPE_INTRA
) {
319 /* search for configured address range for the route's area */
321 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
323 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
324 route_area
->range_table
);
326 /* ranges are ignored when originate backbone routes to transit
328 Otherwise, if ranges are configured, the route is suppressed.
330 if (range
&& !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)
331 && (route
->path
.area_id
!= OSPF_AREA_BACKBONE
332 || !IS_AREA_TRANSIT(area
))) {
334 prefix2str(&range
->prefix
, buf
, sizeof(buf
));
335 zlog_debug("Suppressed by range %s of area %s",
336 buf
, route_area
->name
);
338 ospf6_abr_delete_route(route
, summary
, summary_table
,
344 /* If this is a configured address range */
345 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
346 /* If DoNotAdvertise is set */
347 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
350 "This is the range with DoNotAdvertise set. ignore");
351 ospf6_abr_delete_route(route
, summary
, summary_table
,
356 /* If there are no active prefixes in this range, remove */
357 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
359 zlog_debug("The range is not active. withdraw");
360 ospf6_abr_delete_route(route
, summary
, summary_table
,
366 /* Check export list */
367 if (EXPORT_NAME(area
)) {
368 if (EXPORT_LIST(area
) == NULL
)
370 access_list_lookup(AFI_IP6
, EXPORT_NAME(area
));
372 if (EXPORT_LIST(area
))
373 if (access_list_apply(EXPORT_LIST(area
), &route
->prefix
)
377 &(ADV_ROUTER_IN_PREFIX(
381 "prefix %s was denied by export list",
388 /* Check filter-list */
389 if (PREFIX_LIST_OUT(area
))
390 if (prefix_list_apply(PREFIX_LIST_OUT(area
), &route
->prefix
)
395 &(ADV_ROUTER_IN_PREFIX(&route
->prefix
)),
398 "prefix %s was denied by filter-list out",
404 /* the route is going to be originated. store it in area's summary_table
406 if (summary
== NULL
) {
407 summary
= ospf6_route_copy(route
);
408 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
410 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
411 summary
->path
.origin
.type
=
412 htons(OSPF6_LSTYPE_INTER_ROUTER
);
413 summary
->path
.origin
.id
=
414 ADV_ROUTER_IN_PREFIX(&route
->prefix
);
416 summary
->path
.origin
.type
=
417 htons(OSPF6_LSTYPE_INTER_PREFIX
);
418 summary
->path
.origin
.id
= ospf6_new_ls_id(
419 summary
->path
.origin
.type
,
420 summary
->path
.origin
.adv_router
, area
->lsdb
);
422 summary
= ospf6_route_add(summary
, summary_table
);
424 summary
->type
= route
->type
;
425 monotime(&summary
->changed
);
428 summary
->path
.router_bits
= route
->path
.router_bits
;
429 summary
->path
.options
[0] = route
->path
.options
[0];
430 summary
->path
.options
[1] = route
->path
.options
[1];
431 summary
->path
.options
[2] = route
->path
.options
[2];
432 summary
->path
.prefix_options
= route
->path
.prefix_options
;
433 summary
->path
.area_id
= area
->area_id
;
434 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
435 summary
->path
.subtype
= route
->path
.subtype
;
436 summary
->path
.cost
= route
->path
.cost
;
437 /* summary->nexthop[0] = route->nexthop[0]; */
440 memset(buffer
, 0, sizeof(buffer
));
441 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
443 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
444 router_lsa
= (struct ospf6_inter_router_lsa
445 *)((caddr_t
)lsa_header
446 + sizeof(struct ospf6_lsa_header
));
447 p
= (caddr_t
)router_lsa
+ sizeof(struct ospf6_inter_router_lsa
);
449 /* Fill Inter-Area-Router-LSA */
450 router_lsa
->options
[0] = route
->path
.options
[0];
451 router_lsa
->options
[1] = route
->path
.options
[1];
452 router_lsa
->options
[2] = route
->path
.options
[2];
453 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa
, route
->path
.cost
);
454 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX(&route
->prefix
);
455 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
457 prefix_lsa
= (struct ospf6_inter_prefix_lsa
458 *)((caddr_t
)lsa_header
459 + sizeof(struct ospf6_lsa_header
));
460 p
= (caddr_t
)prefix_lsa
+ sizeof(struct ospf6_inter_prefix_lsa
);
462 /* Fill Inter-Area-Prefix-LSA */
463 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa
, route
->path
.cost
);
464 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
465 prefix_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
468 memcpy(p
, &route
->prefix
.u
.prefix6
,
469 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
470 ospf6_prefix_apply_mask(&prefix_lsa
->prefix
);
471 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
472 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
475 /* Fill LSA Header */
477 lsa_header
->type
= type
;
478 lsa_header
->id
= summary
->path
.origin
.id
;
479 lsa_header
->adv_router
= area
->ospf6
->router_id
;
481 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
482 lsa_header
->adv_router
, area
->lsdb
);
483 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
486 ospf6_lsa_checksum(lsa_header
);
489 lsa
= ospf6_lsa_create(lsa_header
);
492 ospf6_lsa_originate_area(lsa
, area
);
497 void ospf6_abr_range_reset_cost(struct ospf6
*ospf6
)
499 struct listnode
*node
, *nnode
;
500 struct ospf6_area
*oa
;
501 struct ospf6_route
*range
;
503 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
504 for (range
= ospf6_route_head(oa
->range_table
); range
;
505 range
= ospf6_route_next(range
))
506 OSPF6_ABR_RANGE_CLEAR_COST(range
);
509 static inline u_int32_t
ospf6_abr_range_compute_cost(struct ospf6_route
*range
,
512 struct ospf6_route
*ro
;
515 for (ro
= ospf6_route_match_head(&range
->prefix
, o
->route_table
); ro
;
516 ro
= ospf6_route_match_next(&range
->prefix
, ro
)) {
517 if (ro
->path
.area_id
== range
->path
.area_id
518 && (ro
->path
.type
== OSPF6_PATH_TYPE_INTRA
)
519 && !CHECK_FLAG(ro
->flag
, OSPF6_ROUTE_REMOVE
))
520 cost
= MAX(cost
, ro
->path
.cost
);
527 ospf6_abr_range_summary_needs_update(struct ospf6_route
*range
, u_int32_t cost
)
529 int redo_summary
= 0;
531 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
532 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
534 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
535 if (range
->path
.cost
!= 0) {
536 range
->path
.cost
= 0;
540 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
541 && range
->path
.cost
!= range
->path
.u
.cost_config
)) {
542 range
->path
.cost
= range
->path
.u
.cost_config
;
543 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
545 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
546 && range
->path
.cost
!= cost
) {
547 range
->path
.cost
= cost
;
548 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
551 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
552 /* Cost is zero, meaning no active range */
553 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
554 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
558 return (redo_summary
);
561 static void ospf6_abr_range_update(struct ospf6_route
*range
)
564 struct listnode
*node
, *nnode
;
565 struct ospf6_area
*oa
;
566 int summary_orig
= 0;
568 assert(range
->type
== OSPF6_DEST_TYPE_RANGE
);
570 /* update range's cost and active flag */
571 cost
= ospf6_abr_range_compute_cost(range
, ospf6
);
573 /* Non-zero cost is a proxy for active longer prefixes in this range.
574 * If there are active routes covered by this range AND either the
576 * cost has changed or the summarized cost has changed then redo
578 * Alternately, if there are no longer active prefixes and there are
579 * summary announcements, withdraw those announcements.
581 * The don't advertise code relies on the path.cost being set to UNSPEC
583 * work the first time. Subsequent times the path.cost is not 0 anyway
585 * were active ranges.
588 if (ospf6_abr_range_summary_needs_update(range
, cost
)) {
589 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
591 ospf6_abr_originate_summary_to_area(range
, oa
);
593 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
595 if (!CHECK_FLAG(range
->flag
,
596 OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
597 if (IS_OSPF6_DEBUG_ABR
)
598 zlog_debug("Add discard route");
600 ospf6_zebra_add_discard(range
);
603 /* Summary removed or no summary generated as no
605 if (CHECK_FLAG(range
->flag
,
606 OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
607 if (IS_OSPF6_DEBUG_ABR
)
608 zlog_debug("Delete discard route");
610 ospf6_zebra_delete_discard(range
);
616 void ospf6_abr_originate_summary(struct ospf6_route
*route
)
618 struct listnode
*node
, *nnode
;
619 struct ospf6_area
*oa
;
620 struct ospf6_route
*range
= NULL
;
622 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
623 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
624 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
627 ospf6_abr_range_update(range
);
631 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
632 ospf6_abr_originate_summary_to_area(route
, oa
);
635 void ospf6_abr_defaults_to_stub(struct ospf6
*o
)
637 struct listnode
*node
, *nnode
;
638 struct ospf6_area
*oa
;
639 struct ospf6_route
*def
, *route
;
644 def
= ospf6_route_create();
645 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
646 def
->prefix
.family
= AF_INET6
;
647 def
->prefix
.prefixlen
= 0;
648 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
649 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
650 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
651 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
652 def
->path
.area_id
= o
->backbone
->area_id
;
654 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
655 if (!IS_AREA_STUB(oa
)) {
656 /* withdraw defaults when an area switches from stub to
658 route
= ospf6_route_lookup(&def
->prefix
,
661 && (route
->path
.subtype
== def
->path
.subtype
)) {
662 if (IS_OSPF6_DEBUG_ABR
)
664 "Withdrawing default route from non-stubby area %s",
666 SET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
667 ospf6_abr_originate_summary_to_area(def
, oa
);
670 /* announce defaults to stubby areas */
671 if (IS_OSPF6_DEBUG_ABR
)
673 "Announcing default route into stubby area %s",
675 UNSET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
676 ospf6_abr_originate_summary_to_area(def
, oa
);
679 ospf6_route_delete(def
);
682 /* RFC 2328 16.2. Calculating the inter-area routes */
683 void ospf6_abr_examin_summary(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
685 struct prefix prefix
, abr_prefix
;
686 struct ospf6_route_table
*table
= NULL
;
687 struct ospf6_route
*range
, *route
, *old
= NULL
;
688 struct ospf6_route
*abr_entry
;
690 char options
[3] = {0, 0, 0};
691 u_int8_t prefix_options
= 0;
693 u_char router_bits
= 0;
694 char buf
[PREFIX2STR_BUFFER
];
696 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
697 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
699 memset(&prefix
, 0, sizeof(prefix
));
701 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
702 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
)) {
704 zlog_debug("Examin %s in area %s", lsa
->name
, oa
->name
);
708 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
710 prefix
.family
= AF_INET6
;
711 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
712 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, &prefix_lsa
->prefix
);
714 prefix2str(&prefix
, buf
, sizeof(buf
));
715 table
= oa
->ospf6
->route_table
;
716 type
= OSPF6_DEST_TYPE_NETWORK
;
717 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
718 cost
= OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
);
719 } else if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
720 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER
)) {
722 zlog_debug("Examin %s in area %s", lsa
->name
, oa
->name
);
726 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
728 ospf6_linkstate_prefix(router_lsa
->router_id
, htonl(0),
731 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
,
734 table
= oa
->ospf6
->brouter_table
;
735 type
= OSPF6_DEST_TYPE_ROUTER
;
736 options
[0] = router_lsa
->options
[0];
737 options
[1] = router_lsa
->options
[1];
738 options
[2] = router_lsa
->options
[2];
739 cost
= OSPF6_ABR_SUMMARY_METRIC(router_lsa
);
740 SET_FLAG(router_bits
, OSPF6_ROUTER_BIT_E
);
744 /* Find existing route */
745 route
= ospf6_route_lookup(&prefix
, table
);
747 ospf6_route_lock(route
);
748 while (route
&& ospf6_route_is_prefix(&prefix
, route
)) {
749 if (route
->path
.area_id
== oa
->area_id
750 && route
->path
.origin
.type
== lsa
->header
->type
751 && route
->path
.origin
.id
== lsa
->header
->id
752 && route
->path
.origin
.adv_router
== lsa
->header
->adv_router
753 && !CHECK_FLAG(route
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
755 route
= ospf6_route_next(route
);
758 ospf6_route_unlock(route
);
760 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
761 if (cost
== OSPF_LS_INFINITY
) {
763 zlog_debug("cost is LS_INFINITY, ignore");
765 ospf6_route_remove(old
, table
);
768 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
770 zlog_debug("LSA is MaxAge, ignore");
772 ospf6_route_remove(old
, table
);
776 /* (2) if the LSA is self-originated, ignore */
777 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
779 zlog_debug("LSA is self-originated, ignore");
781 ospf6_route_remove(old
, table
);
785 /* (3) if the prefix is equal to an active configured address range */
786 /* or if the NU bit is set in the prefix */
787 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
788 range
= ospf6_route_lookup(&prefix
, oa
->range_table
);
792 "Prefix is equal to address range, ignore");
794 ospf6_route_remove(old
, table
);
798 if (CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
799 OSPF6_PREFIX_OPTION_NU
)
800 || CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
801 OSPF6_PREFIX_OPTION_LA
)) {
803 zlog_debug("Prefix has NU/LA bit set, ignore");
805 ospf6_route_remove(old
, table
);
810 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
811 /* To pass test suites */
812 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
813 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
815 zlog_debug("Prefix has NU/LA bit set, ignore");
817 ospf6_route_remove(old
, table
);
821 /* Avoid infinite recursion if someone has maliciously announced
823 Inter-Router LSA for an ABR
825 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
828 "Ignorning Inter-Router LSA for an ABR (%s)",
831 ospf6_route_remove(old
, table
);
837 /* (4) if the routing table entry for the ABR does not exist */
838 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
839 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
840 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
841 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
842 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
844 zlog_debug("ABR router entry does not exist, ignore");
846 ospf6_route_remove(old
, table
);
850 /* Check import list */
851 if (IMPORT_NAME(oa
)) {
852 if (IMPORT_LIST(oa
) == NULL
)
854 access_list_lookup(AFI_IP6
, IMPORT_NAME(oa
));
857 if (access_list_apply(IMPORT_LIST(oa
), &prefix
)
861 "Prefix was denied by import-list");
863 ospf6_route_remove(old
, table
);
868 /* Check input prefix-list */
869 if (PREFIX_LIST_IN(oa
))
870 if (prefix_list_apply(PREFIX_LIST_IN(oa
), &prefix
)
873 zlog_debug("Prefix was denied by prefix-list");
875 ospf6_route_remove(old
, table
);
879 /* (5),(6): the path preference is handled by the sorting
880 in the routing table. Always install the path by substituting
881 old route (if any). */
883 route
= ospf6_route_copy(old
);
885 route
= ospf6_route_create();
888 route
->prefix
= prefix
;
889 route
->path
.origin
.type
= lsa
->header
->type
;
890 route
->path
.origin
.id
= lsa
->header
->id
;
891 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
892 route
->path
.router_bits
= router_bits
;
893 route
->path
.options
[0] = options
[0];
894 route
->path
.options
[1] = options
[1];
895 route
->path
.options
[2] = options
[2];
896 route
->path
.prefix_options
= prefix_options
;
897 route
->path
.area_id
= oa
->area_id
;
898 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
899 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
901 ospf6_route_copy_nexthops(route
, abr_entry
);
904 /* (7) If the routes are identical, copy the next hops over to existing
905 route. ospf6's route table implementation will otherwise string both
906 routes, but keep the older one as the best route since the routes
909 old
= ospf6_route_lookup(&prefix
, table
);
911 if (old
&& (ospf6_route_cmp(route
, old
) == 0)) {
912 ospf6_route_merge_nexthops(old
, route
);
915 zlog_debug("%s: Update route: %s nh count %u",
916 __PRETTY_FUNCTION__
, buf
,
917 listcount(route
->nh_list
));
921 (*table
->hook_add
)(old
);
923 /* Delete new route */
924 ospf6_route_delete(route
);
927 zlog_debug("Install route: %s nh count %u", buf
,
928 listcount(route
->nh_list
));
929 /* ospf6_ia_add_nw_route (table, &prefix, route); */
930 ospf6_route_add(route
, table
);
934 void ospf6_abr_examin_brouter(u_int32_t router_id
)
936 struct ospf6_lsa
*lsa
;
937 struct ospf6_area
*oa
;
940 if (ospf6_is_router_abr(ospf6
))
941 oa
= ospf6
->backbone
;
943 oa
= listgetdata(listhead(ospf6
->area_list
));
946 * It is possible to designate a non backbone
947 * area first. If that is the case safely
948 * fall out of this function.
953 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
954 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
955 ospf6_abr_examin_summary(lsa
, oa
);
957 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
958 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router_id
, lsa
))
959 ospf6_abr_examin_summary(lsa
, oa
);
962 void ospf6_abr_reimport(struct ospf6_area
*oa
)
964 struct ospf6_lsa
*lsa
;
967 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
968 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
969 ospf6_abr_examin_summary(lsa
, oa
);
971 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
972 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
973 ospf6_abr_examin_summary(lsa
, oa
);
976 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
978 struct ospf6_route
*route
;
980 if (IS_OSPF6_DEBUG_ABR
)
981 zlog_debug("Re-examining Inter-Prefix Summaries");
983 for (route
= ospf6_route_head(o
->route_table
); route
;
984 route
= ospf6_route_next(route
))
985 ospf6_abr_originate_summary(route
);
987 if (IS_OSPF6_DEBUG_ABR
)
988 zlog_debug("Finished re-examining Inter-Prefix Summaries");
992 /* Display functions */
993 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
994 char *buf
, int buflen
,
997 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1002 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1005 ospf6_prefix_in6_addr(&in6
, &prefix_lsa
->prefix
);
1007 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1008 sprintf(&buf
[strlen(buf
)], "/%d",
1009 prefix_lsa
->prefix
.prefix_length
);
1016 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1017 struct ospf6_lsa
*lsa
)
1019 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1020 char buf
[INET6_ADDRSTRLEN
];
1022 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1025 vty_out(vty
, " Metric: %lu\n",
1026 (u_long
)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
));
1028 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
, buf
,
1030 vty_out(vty
, " Prefix Options: %s\n", buf
);
1032 vty_out(vty
, " Prefix: %s\n",
1033 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa
, buf
,
1039 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1040 char *buf
, int buflen
,
1043 struct ospf6_inter_router_lsa
*router_lsa
;
1047 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1052 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1058 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1059 struct ospf6_lsa
*lsa
)
1061 struct ospf6_inter_router_lsa
*router_lsa
;
1064 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1067 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1068 vty_out(vty
, " Options: %s\n", buf
);
1069 vty_out(vty
, " Metric: %lu\n",
1070 (u_long
)OSPF6_ABR_SUMMARY_METRIC(router_lsa
));
1072 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1073 vty_out(vty
, " Destination Router ID: %s\n", buf
);
1078 /* Debug commands */
1079 DEFUN (debug_ospf6_abr
,
1080 debug_ospf6_abr_cmd
,
1084 "Debug OSPFv3 ABR function\n"
1087 OSPF6_DEBUG_ABR_ON();
1091 DEFUN (no_debug_ospf6_abr
,
1092 no_debug_ospf6_abr_cmd
,
1093 "no debug ospf6 abr",
1097 "Debug OSPFv3 ABR function\n"
1100 OSPF6_DEBUG_ABR_OFF();
1104 int config_write_ospf6_debug_abr(struct vty
*vty
)
1106 if (IS_OSPF6_DEBUG_ABR
)
1107 vty_out(vty
, "debug ospf6 abr\n");
1111 void install_element_ospf6_debug_abr(void)
1113 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1114 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1115 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1116 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1119 struct ospf6_lsa_handler inter_prefix_handler
= {
1120 .lh_type
= OSPF6_LSTYPE_INTER_PREFIX
,
1121 .lh_name
= "Inter-Prefix",
1122 .lh_short_name
= "IAP",
1123 .lh_show
= ospf6_inter_area_prefix_lsa_show
,
1124 .lh_get_prefix_str
= ospf6_inter_area_prefix_lsa_get_prefix_str
,
1127 struct ospf6_lsa_handler inter_router_handler
= {
1128 .lh_type
= OSPF6_LSTYPE_INTER_ROUTER
,
1129 .lh_name
= "Inter-Router",
1130 .lh_short_name
= "IAR",
1131 .lh_show
= ospf6_inter_area_router_lsa_show
,
1132 .lh_get_prefix_str
= ospf6_inter_area_router_lsa_get_prefix_str
,
1135 void ospf6_abr_init(void)
1137 ospf6_install_lsa_handler(&inter_prefix_handler
);
1138 ospf6_install_lsa_handler(&inter_router_handler
);