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
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
35 #include "ospf6_proto.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_route.h"
39 #include "ospf6_lsdb.h"
40 #include "ospf6_message.h"
41 #include "ospf6_zebra.h"
43 #include "ospf6_top.h"
44 #include "ospf6_area.h"
45 #include "ospf6_interface.h"
46 #include "ospf6_neighbor.h"
48 #include "ospf6_flood.h"
49 #include "ospf6_intra.h"
50 #include "ospf6_abr.h"
53 unsigned char conf_debug_ospf6_abr
;
55 int ospf6_is_router_abr(struct ospf6
*o
)
57 struct listnode
*node
;
58 struct ospf6_area
*oa
;
61 for (ALL_LIST_ELEMENTS_RO(o
->area_list
, node
, oa
))
62 if (IS_AREA_ENABLED(oa
))
70 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route
*route
,
71 struct ospf6_area
*area
)
73 struct ospf6_interface
*oi
;
75 oi
= ospf6_interface_lookup_by_ifindex(
76 ospf6_route_get_first_nh_index(route
));
77 if (oi
&& oi
->area
&& oi
->area
== area
)
83 static void ospf6_abr_delete_route(struct ospf6_route
*range
,
84 struct ospf6_route
*summary
,
85 struct ospf6_route_table
*summary_table
,
86 struct ospf6_lsa
*old
)
89 ospf6_route_remove(summary
, summary_table
);
92 if (old
&& !OSPF6_LSA_IS_MAXAGE(old
))
96 void ospf6_abr_enable_area(struct ospf6_area
*area
)
98 struct ospf6_area
*oa
;
99 struct listnode
*node
, *nnode
;
101 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
102 /* update B bit for each area */
103 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
106 void ospf6_abr_disable_area(struct ospf6_area
*area
)
108 struct ospf6_area
*oa
;
109 struct ospf6_route
*ro
, *nro
;
110 struct ospf6_lsa
*old
;
111 struct listnode
*node
, *nnode
;
113 /* Withdraw all summary prefixes previously originated */
114 for (ro
= ospf6_route_head(area
->summary_prefix
); ro
; ro
= nro
) {
115 nro
= ospf6_route_next(ro
);
116 old
= ospf6_lsdb_lookup(ro
->path
.origin
.type
,
118 area
->ospf6
->router_id
, area
->lsdb
);
120 ospf6_lsa_purge(old
);
121 ospf6_route_remove(ro
, area
->summary_prefix
);
124 /* Withdraw all summary router-routes previously originated */
125 for (ro
= ospf6_route_head(area
->summary_router
); ro
; ro
= nro
) {
126 nro
= ospf6_route_next(ro
);
127 old
= ospf6_lsdb_lookup(ro
->path
.origin
.type
,
129 area
->ospf6
->router_id
, area
->lsdb
);
131 ospf6_lsa_purge(old
);
132 ospf6_route_remove(ro
, area
->summary_router
);
135 /* Schedule Router-LSA for each area (ABR status may change) */
136 for (ALL_LIST_ELEMENTS(area
->ospf6
->area_list
, node
, nnode
, oa
))
137 /* update B bit for each area */
138 OSPF6_ROUTER_LSA_SCHEDULE(oa
);
141 /* RFC 2328 12.4.3. Summary-LSAs */
142 /* Returns 1 if a summary LSA has been generated for the area */
143 /* This is used by the area/range logic to add/remove blackhole routes */
144 int ospf6_abr_originate_summary_to_area(struct ospf6_route
*route
,
145 struct ospf6_area
*area
)
147 struct ospf6_lsa
*lsa
, *old
= NULL
;
148 struct ospf6_route
*summary
, *range
= NULL
;
149 struct ospf6_area
*route_area
;
150 char buffer
[OSPF6_MAX_LSASIZE
];
151 struct ospf6_lsa_header
*lsa_header
;
153 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
154 struct ospf6_inter_router_lsa
*router_lsa
;
155 struct ospf6_route_table
*summary_table
= NULL
;
157 char buf
[PREFIX2STR_BUFFER
];
160 /* Only destination type network, range or ASBR are considered */
161 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
162 && route
->type
!= OSPF6_DEST_TYPE_RANGE
163 && ((route
->type
!= OSPF6_DEST_TYPE_ROUTER
)
164 || !CHECK_FLAG(route
->path
.router_bits
, OSPF6_ROUTER_BIT_E
))) {
167 "Route type is none of network, range nor ASBR, ignore");
171 /* AS External routes are never considered */
172 if (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
173 || route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
) {
175 zlog_debug("Path type is external, skip");
179 /* do not generate if the path's area is the same as target area */
180 if (route
->path
.area_id
== area
->area_id
) {
182 zlog_debug("The route is in the area itself, ignore");
186 /* do not generate if the nexthops belongs to the target area */
187 if (ospf6_abr_nexthops_belong_to_area(route
, area
)) {
190 "The route's nexthop is in the same area, ignore");
194 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
195 if (ADV_ROUTER_IN_PREFIX(&route
->prefix
)
196 == area
->ospf6
->router_id
) {
198 &(ADV_ROUTER_IN_PREFIX(&route
->prefix
)), buf
,
201 "%s: Skipping ASBR announcement for ABR (%s)",
207 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
208 if (IS_OSPF6_DEBUG_ABR
209 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER
)) {
212 &(ADV_ROUTER_IN_PREFIX(&route
->prefix
)), buf
,
214 zlog_debug("Originating summary in area %s for ASBR %s",
217 summary_table
= area
->summary_router
;
219 if (IS_OSPF6_DEBUG_ABR
220 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX
)) {
222 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
223 zlog_debug("Originating summary in area %s for %s",
226 summary_table
= area
->summary_prefix
;
229 summary
= ospf6_route_lookup(&route
->prefix
, summary_table
);
231 old
= ospf6_lsdb_lookup(summary
->path
.origin
.type
,
232 summary
->path
.origin
.id
,
233 area
->ospf6
->router_id
, area
->lsdb
);
235 /* if this route has just removed, remove corresponding LSA */
236 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)) {
239 "The route has just removed, purge previous LSA");
241 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
242 /* Whether the route have active longer prefix */
243 if (!CHECK_FLAG(route
->flag
,
244 OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
247 "The range is not active. withdraw");
249 ospf6_abr_delete_route(route
, summary
,
253 ospf6_lsa_purge(old
);
258 if ((route
->type
== OSPF6_DEST_TYPE_ROUTER
) && IS_AREA_STUB(area
)) {
261 "Area has been stubbed, purge Inter-Router LSA");
263 ospf6_abr_delete_route(route
, summary
, summary_table
, old
);
268 && (route
->path
.subtype
!= OSPF6_PATH_SUBTYPE_DEFAULT_RT
)) {
270 zlog_debug("Area has been stubbed, purge prefix LSA");
272 ospf6_abr_delete_route(route
, summary
, summary_table
, old
);
276 /* do not generate if the route cost is greater or equal to LSInfinity
278 if (route
->path
.cost
>= OSPF_LS_INFINITY
) {
279 /* When we're clearing the range route because all active
281 * under the range are gone, we set the range's cost to
282 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
283 * don't want to trigger the code here for that. This code is
285 * handling routes that have gone to infinity. The range removal
289 if ((route
->type
!= OSPF6_DEST_TYPE_RANGE
)
290 && (route
->path
.cost
!= OSPF_AREA_RANGE_COST_UNSPEC
)) {
293 "The cost exceeds LSInfinity, withdraw");
295 ospf6_lsa_purge(old
);
300 /* if this is a route to ASBR */
301 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
302 /* Only the prefered best path is considered */
303 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_BEST
)) {
306 "This is the secondary path to the ASBR, ignore");
307 ospf6_abr_delete_route(route
, summary
, summary_table
,
312 /* Do not generate if the area is stub */
316 /* if this is an intra-area route, this may be suppressed by aggregation
318 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
319 && route
->path
.type
== OSPF6_PATH_TYPE_INTRA
) {
320 /* search for configured address range for the route's area */
322 ospf6_area_lookup(route
->path
.area_id
, area
->ospf6
);
324 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
325 route_area
->range_table
);
327 /* ranges are ignored when originate backbone routes to transit
329 Otherwise, if ranges are configured, the route is suppressed.
331 if (range
&& !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)
332 && (route
->path
.area_id
!= OSPF_AREA_BACKBONE
333 || !IS_AREA_TRANSIT(area
))) {
335 prefix2str(&range
->prefix
, buf
, sizeof(buf
));
336 zlog_debug("Suppressed by range %s of area %s",
337 buf
, route_area
->name
);
339 ospf6_abr_delete_route(route
, summary
, summary_table
,
345 /* If this is a configured address range */
346 if (route
->type
== OSPF6_DEST_TYPE_RANGE
) {
347 /* If DoNotAdvertise is set */
348 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
351 "This is the range with DoNotAdvertise set. ignore");
352 ospf6_abr_delete_route(route
, summary
, summary_table
,
357 /* If there are no active prefixes in this range, remove */
358 if (!CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
360 zlog_debug("The range is not active. withdraw");
361 ospf6_abr_delete_route(route
, summary
, summary_table
,
367 /* Check export list */
368 if (EXPORT_NAME(area
)) {
369 if (EXPORT_LIST(area
) == NULL
)
371 access_list_lookup(AFI_IP6
, EXPORT_NAME(area
));
373 if (EXPORT_LIST(area
))
374 if (access_list_apply(EXPORT_LIST(area
), &route
->prefix
)
378 &(ADV_ROUTER_IN_PREFIX(
382 "prefix %s was denied by export list",
389 /* Check filter-list */
390 if (PREFIX_NAME_OUT(area
)) {
391 if (PREFIX_LIST_OUT(area
) == NULL
)
392 PREFIX_LIST_OUT(area
) = prefix_list_lookup(
393 AFI_IP6
, PREFIX_NAME_OUT(area
));
395 if (PREFIX_LIST_OUT(area
))
396 if (prefix_list_apply(PREFIX_LIST_OUT(area
),
401 &(ADV_ROUTER_IN_PREFIX(
405 "prefix %s was denied by filter-list out",
412 /* the route is going to be originated. store it in area's summary_table
414 if (summary
== NULL
) {
415 summary
= ospf6_route_copy(route
);
416 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
418 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
419 summary
->path
.origin
.type
=
420 htons(OSPF6_LSTYPE_INTER_ROUTER
);
421 summary
->path
.origin
.id
=
422 ADV_ROUTER_IN_PREFIX(&route
->prefix
);
424 summary
->path
.origin
.type
=
425 htons(OSPF6_LSTYPE_INTER_PREFIX
);
426 summary
->path
.origin
.id
= ospf6_new_ls_id(
427 summary
->path
.origin
.type
,
428 summary
->path
.origin
.adv_router
, area
->lsdb
);
430 summary
= ospf6_route_add(summary
, summary_table
);
432 summary
->type
= route
->type
;
433 monotime(&summary
->changed
);
436 summary
->path
.router_bits
= route
->path
.router_bits
;
437 summary
->path
.options
[0] = route
->path
.options
[0];
438 summary
->path
.options
[1] = route
->path
.options
[1];
439 summary
->path
.options
[2] = route
->path
.options
[2];
440 summary
->path
.prefix_options
= route
->path
.prefix_options
;
441 summary
->path
.area_id
= area
->area_id
;
442 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
443 summary
->path
.subtype
= route
->path
.subtype
;
444 summary
->path
.cost
= route
->path
.cost
;
445 /* summary->nexthop[0] = route->nexthop[0]; */
448 memset(buffer
, 0, sizeof(buffer
));
449 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
451 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
) {
452 router_lsa
= (struct ospf6_inter_router_lsa
453 *)((caddr_t
)lsa_header
454 + sizeof(struct ospf6_lsa_header
));
455 p
= (caddr_t
)router_lsa
+ sizeof(struct ospf6_inter_router_lsa
);
457 /* Fill Inter-Area-Router-LSA */
458 router_lsa
->options
[0] = route
->path
.options
[0];
459 router_lsa
->options
[1] = route
->path
.options
[1];
460 router_lsa
->options
[2] = route
->path
.options
[2];
461 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa
, route
->path
.cost
);
462 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX(&route
->prefix
);
463 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
465 prefix_lsa
= (struct ospf6_inter_prefix_lsa
466 *)((caddr_t
)lsa_header
467 + sizeof(struct ospf6_lsa_header
));
468 p
= (caddr_t
)prefix_lsa
+ sizeof(struct ospf6_inter_prefix_lsa
);
470 /* Fill Inter-Area-Prefix-LSA */
471 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa
, route
->path
.cost
);
472 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
473 prefix_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
476 memcpy(p
, &route
->prefix
.u
.prefix6
,
477 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
478 ospf6_prefix_apply_mask(&prefix_lsa
->prefix
);
479 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
480 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
483 /* Fill LSA Header */
485 lsa_header
->type
= type
;
486 lsa_header
->id
= summary
->path
.origin
.id
;
487 lsa_header
->adv_router
= area
->ospf6
->router_id
;
489 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
490 lsa_header
->adv_router
, area
->lsdb
);
491 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
494 ospf6_lsa_checksum(lsa_header
);
497 lsa
= ospf6_lsa_create(lsa_header
);
500 ospf6_lsa_originate_area(lsa
, area
);
505 void ospf6_abr_range_reset_cost(struct ospf6
*ospf6
)
507 struct listnode
*node
, *nnode
;
508 struct ospf6_area
*oa
;
509 struct ospf6_route
*range
;
511 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
512 for (range
= ospf6_route_head(oa
->range_table
); range
;
513 range
= ospf6_route_next(range
))
514 OSPF6_ABR_RANGE_CLEAR_COST(range
);
517 static inline u_int32_t
ospf6_abr_range_compute_cost(struct ospf6_route
*range
,
520 struct ospf6_route
*ro
;
523 for (ro
= ospf6_route_match_head(&range
->prefix
, o
->route_table
); ro
;
524 ro
= ospf6_route_match_next(&range
->prefix
, ro
)) {
525 if (ro
->path
.area_id
== range
->path
.area_id
526 && (ro
->path
.type
== OSPF6_PATH_TYPE_INTRA
)
527 && !CHECK_FLAG(ro
->flag
, OSPF6_ROUTE_REMOVE
))
528 cost
= MAX(cost
, ro
->path
.cost
);
535 ospf6_abr_range_summary_needs_update(struct ospf6_route
*range
, u_int32_t cost
)
537 int redo_summary
= 0;
539 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
540 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
542 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
)) {
543 if (range
->path
.cost
!= 0) {
544 range
->path
.cost
= 0;
548 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
549 && range
->path
.cost
!= range
->path
.u
.cost_config
)) {
550 range
->path
.cost
= range
->path
.u
.cost_config
;
551 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
553 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
)
554 && range
->path
.cost
!= cost
) {
555 range
->path
.cost
= cost
;
556 SET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
559 } else if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)) {
560 /* Cost is zero, meaning no active range */
561 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
562 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
566 return (redo_summary
);
569 static void ospf6_abr_range_update(struct ospf6_route
*range
)
572 struct listnode
*node
, *nnode
;
573 struct ospf6_area
*oa
;
574 int summary_orig
= 0;
576 assert(range
->type
== OSPF6_DEST_TYPE_RANGE
);
578 /* update range's cost and active flag */
579 cost
= ospf6_abr_range_compute_cost(range
, ospf6
);
581 /* Non-zero cost is a proxy for active longer prefixes in this range.
582 * If there are active routes covered by this range AND either the
584 * cost has changed or the summarized cost has changed then redo
586 * Alternately, if there are no longer active prefixes and there are
587 * summary announcements, withdraw those announcements.
589 * The don't advertise code relies on the path.cost being set to UNSPEC
591 * work the first time. Subsequent times the path.cost is not 0 anyway
593 * were active ranges.
596 if (ospf6_abr_range_summary_needs_update(range
, cost
)) {
597 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
599 ospf6_abr_originate_summary_to_area(range
, oa
);
601 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
)
603 if (!CHECK_FLAG(range
->flag
,
604 OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
605 if (IS_OSPF6_DEBUG_ABR
)
606 zlog_debug("Add discard route");
608 ospf6_zebra_add_discard(range
);
611 /* Summary removed or no summary generated as no
613 if (CHECK_FLAG(range
->flag
,
614 OSPF6_ROUTE_BLACKHOLE_ADDED
)) {
615 if (IS_OSPF6_DEBUG_ABR
)
616 zlog_debug("Delete discard route");
618 ospf6_zebra_delete_discard(range
);
624 void ospf6_abr_originate_summary(struct ospf6_route
*route
)
626 struct listnode
*node
, *nnode
;
627 struct ospf6_area
*oa
;
628 struct ospf6_route
*range
= NULL
;
630 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
) {
631 oa
= ospf6_area_lookup(route
->path
.area_id
, ospf6
);
632 range
= ospf6_route_lookup_bestmatch(&route
->prefix
,
635 ospf6_abr_range_update(range
);
639 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
))
640 ospf6_abr_originate_summary_to_area(route
, oa
);
643 void ospf6_abr_defaults_to_stub(struct ospf6
*o
)
645 struct listnode
*node
, *nnode
;
646 struct ospf6_area
*oa
;
647 struct ospf6_route
*def
, *route
;
652 def
= ospf6_route_create();
653 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
654 def
->prefix
.family
= AF_INET6
;
655 def
->prefix
.prefixlen
= 0;
656 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
657 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
658 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
659 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
660 def
->path
.area_id
= o
->backbone
->area_id
;
662 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
663 if (!IS_AREA_STUB(oa
)) {
664 /* withdraw defaults when an area switches from stub to
666 route
= ospf6_route_lookup(&def
->prefix
,
669 && (route
->path
.subtype
== def
->path
.subtype
)) {
670 if (IS_OSPF6_DEBUG_ABR
)
672 "Withdrawing default route from non-stubby area %s",
674 SET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
675 ospf6_abr_originate_summary_to_area(def
, oa
);
678 /* announce defaults to stubby areas */
679 if (IS_OSPF6_DEBUG_ABR
)
681 "Announcing default route into stubby area %s",
683 UNSET_FLAG(def
->flag
, OSPF6_ROUTE_REMOVE
);
684 ospf6_abr_originate_summary_to_area(def
, oa
);
687 ospf6_route_delete(def
);
690 /* RFC 2328 16.2. Calculating the inter-area routes */
691 void ospf6_abr_examin_summary(struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
693 struct prefix prefix
, abr_prefix
;
694 struct ospf6_route_table
*table
= NULL
;
695 struct ospf6_route
*range
, *route
, *old
= NULL
;
696 struct ospf6_route
*abr_entry
;
698 char options
[3] = {0, 0, 0};
699 u_int8_t prefix_options
= 0;
701 u_char router_bits
= 0;
702 char buf
[PREFIX2STR_BUFFER
];
704 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
705 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
707 memset(&prefix
, 0, sizeof(prefix
));
709 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
710 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX
)) {
712 zlog_debug("Examin %s in area %s", lsa
->name
, oa
->name
);
716 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
718 prefix
.family
= AF_INET6
;
719 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
720 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, &prefix_lsa
->prefix
);
722 prefix2str(&prefix
, buf
, sizeof(buf
));
723 table
= oa
->ospf6
->route_table
;
724 type
= OSPF6_DEST_TYPE_NETWORK
;
725 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
726 cost
= OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
);
727 } else if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
728 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER
)) {
730 zlog_debug("Examin %s in area %s", lsa
->name
, oa
->name
);
734 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
736 ospf6_linkstate_prefix(router_lsa
->router_id
, htonl(0),
739 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
,
742 table
= oa
->ospf6
->brouter_table
;
743 type
= OSPF6_DEST_TYPE_ROUTER
;
744 options
[0] = router_lsa
->options
[0];
745 options
[1] = router_lsa
->options
[1];
746 options
[2] = router_lsa
->options
[2];
747 cost
= OSPF6_ABR_SUMMARY_METRIC(router_lsa
);
748 SET_FLAG(router_bits
, OSPF6_ROUTER_BIT_E
);
752 /* Find existing route */
753 route
= ospf6_route_lookup(&prefix
, table
);
755 ospf6_route_lock(route
);
756 while (route
&& ospf6_route_is_prefix(&prefix
, route
)) {
757 if (route
->path
.area_id
== oa
->area_id
758 && route
->path
.origin
.type
== lsa
->header
->type
759 && route
->path
.origin
.id
== lsa
->header
->id
760 && route
->path
.origin
.adv_router
== lsa
->header
->adv_router
761 && !CHECK_FLAG(route
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
763 route
= ospf6_route_next(route
);
766 ospf6_route_unlock(route
);
768 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
769 if (cost
== OSPF_LS_INFINITY
) {
771 zlog_debug("cost is LS_INFINITY, ignore");
773 ospf6_route_remove(old
, table
);
776 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
778 zlog_debug("LSA is MaxAge, ignore");
780 ospf6_route_remove(old
, table
);
784 /* (2) if the LSA is self-originated, ignore */
785 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
) {
787 zlog_debug("LSA is self-originated, ignore");
789 ospf6_route_remove(old
, table
);
793 /* (3) if the prefix is equal to an active configured address range */
794 /* or if the NU bit is set in the prefix */
795 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_PREFIX
)) {
796 range
= ospf6_route_lookup(&prefix
, oa
->range_table
);
800 "Prefix is equal to address range, ignore");
802 ospf6_route_remove(old
, table
);
806 if (CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
807 OSPF6_PREFIX_OPTION_NU
)
808 || CHECK_FLAG(prefix_lsa
->prefix
.prefix_options
,
809 OSPF6_PREFIX_OPTION_LA
)) {
811 zlog_debug("Prefix has NU/LA bit set, ignore");
813 ospf6_route_remove(old
, table
);
818 if (lsa
->header
->type
== htons(OSPF6_LSTYPE_INTER_ROUTER
)) {
819 /* To pass test suites */
820 if (!OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_R
)
821 || !OSPF6_OPT_ISSET(router_lsa
->options
, OSPF6_OPT_V6
)) {
823 zlog_debug("Prefix has NU/LA bit set, ignore");
825 ospf6_route_remove(old
, table
);
829 /* Avoid infinite recursion if someone has maliciously announced
831 Inter-Router LSA for an ABR
833 if (lsa
->header
->adv_router
== router_lsa
->router_id
) {
836 "Ignorning Inter-Router LSA for an ABR (%s)",
839 ospf6_route_remove(old
, table
);
845 /* (4) if the routing table entry for the ABR does not exist */
846 ospf6_linkstate_prefix(lsa
->header
->adv_router
, htonl(0), &abr_prefix
);
847 abr_entry
= ospf6_route_lookup(&abr_prefix
, oa
->ospf6
->brouter_table
);
848 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
849 || CHECK_FLAG(abr_entry
->flag
, OSPF6_ROUTE_REMOVE
)
850 || !CHECK_FLAG(abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
)) {
852 zlog_debug("ABR router entry does not exist, ignore");
854 ospf6_route_remove(old
, table
);
858 /* Check import list */
859 if (IMPORT_NAME(oa
)) {
860 if (IMPORT_LIST(oa
) == NULL
)
862 access_list_lookup(AFI_IP6
, IMPORT_NAME(oa
));
865 if (access_list_apply(IMPORT_LIST(oa
), &prefix
)
869 "Prefix was denied by import-list");
871 ospf6_route_remove(old
, table
);
876 /* Check input prefix-list */
877 if (PREFIX_NAME_IN(oa
)) {
878 if (PREFIX_LIST_IN(oa
) == NULL
)
880 prefix_list_lookup(AFI_IP6
, PREFIX_NAME_IN(oa
));
882 if (PREFIX_LIST_IN(oa
))
883 if (prefix_list_apply(PREFIX_LIST_IN(oa
), &prefix
)
887 "Prefix was denied by prefix-list");
889 ospf6_route_remove(old
, table
);
894 /* (5),(6): the path preference is handled by the sorting
895 in the routing table. Always install the path by substituting
896 old route (if any). */
898 route
= ospf6_route_copy(old
);
900 route
= ospf6_route_create();
903 route
->prefix
= prefix
;
904 route
->path
.origin
.type
= lsa
->header
->type
;
905 route
->path
.origin
.id
= lsa
->header
->id
;
906 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
907 route
->path
.router_bits
= router_bits
;
908 route
->path
.options
[0] = options
[0];
909 route
->path
.options
[1] = options
[1];
910 route
->path
.options
[2] = options
[2];
911 route
->path
.prefix_options
= prefix_options
;
912 route
->path
.area_id
= oa
->area_id
;
913 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
914 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
916 ospf6_route_copy_nexthops(route
, abr_entry
);
918 /* (7) If the routes are identical, copy the next hops over to existing
919 route. ospf6's route table implementation will otherwise string both
920 routes, but keep the older one as the best route since the routes
923 old
= ospf6_route_lookup(&prefix
, table
);
925 if (old
&& (ospf6_route_cmp(route
, old
) == 0)) {
926 ospf6_route_merge_nexthops(old
, route
);
929 (*table
->hook_add
)(old
);
931 /* Delete new route */
932 ospf6_route_delete(route
);
935 zlog_debug("Install route: %s", buf
);
936 /* ospf6_ia_add_nw_route (table, &prefix, route); */
937 ospf6_route_add(route
, table
);
941 void ospf6_abr_examin_brouter(u_int32_t router_id
)
943 struct ospf6_lsa
*lsa
;
944 struct ospf6_area
*oa
;
947 if (ospf6_is_router_abr(ospf6
))
948 oa
= ospf6
->backbone
;
950 oa
= listgetdata(listhead(ospf6
->area_list
));
953 * It is possible to designate a non backbone
954 * area first. If that is the case safely
955 * fall out of this function.
960 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
961 for (lsa
= ospf6_lsdb_type_router_head(type
, router_id
, oa
->lsdb
); lsa
;
962 lsa
= ospf6_lsdb_type_router_next(type
, router_id
, lsa
))
963 ospf6_abr_examin_summary(lsa
, oa
);
965 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
966 for (lsa
= ospf6_lsdb_type_router_head(type
, router_id
, oa
->lsdb
); lsa
;
967 lsa
= ospf6_lsdb_type_router_next(type
, router_id
, lsa
))
968 ospf6_abr_examin_summary(lsa
, oa
);
971 void ospf6_abr_reimport(struct ospf6_area
*oa
)
973 struct ospf6_lsa
*lsa
;
976 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
977 for (lsa
= ospf6_lsdb_type_head(type
, oa
->lsdb
); lsa
;
978 lsa
= ospf6_lsdb_type_next(type
, lsa
))
979 ospf6_abr_examin_summary(lsa
, oa
);
981 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
982 for (lsa
= ospf6_lsdb_type_head(type
, oa
->lsdb
); lsa
;
983 lsa
= ospf6_lsdb_type_next(type
, lsa
))
984 ospf6_abr_examin_summary(lsa
, oa
);
987 void ospf6_abr_prefix_resummarize(struct ospf6
*o
)
989 struct ospf6_route
*route
;
991 if (IS_OSPF6_DEBUG_ABR
)
992 zlog_debug("Re-examining Inter-Prefix Summaries");
994 for (route
= ospf6_route_head(o
->route_table
); route
;
995 route
= ospf6_route_next(route
))
996 ospf6_abr_originate_summary(route
);
998 if (IS_OSPF6_DEBUG_ABR
)
999 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1003 /* Display functions */
1004 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1005 char *buf
, int buflen
,
1008 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1009 struct in6_addr in6
;
1013 (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1016 ospf6_prefix_in6_addr(&in6
, &prefix_lsa
->prefix
);
1018 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
1019 sprintf(&buf
[strlen(buf
)], "/%d",
1020 prefix_lsa
->prefix
.prefix_length
);
1027 static int ospf6_inter_area_prefix_lsa_show(struct vty
*vty
,
1028 struct ospf6_lsa
*lsa
)
1030 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1031 char buf
[INET6_ADDRSTRLEN
];
1033 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1036 vty_out(vty
, " Metric: %lu%s",
1037 (u_long
)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa
), VNL
);
1039 ospf6_prefix_options_printbuf(prefix_lsa
->prefix
.prefix_options
, buf
,
1041 vty_out(vty
, " Prefix Options: %s%s", buf
, VNL
);
1043 vty_out(vty
, " Prefix: %s%s",
1044 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa
, buf
,
1051 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
1052 char *buf
, int buflen
,
1055 struct ospf6_inter_router_lsa
*router_lsa
;
1059 (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1064 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1070 static int ospf6_inter_area_router_lsa_show(struct vty
*vty
,
1071 struct ospf6_lsa
*lsa
)
1073 struct ospf6_inter_router_lsa
*router_lsa
;
1076 router_lsa
= (struct ospf6_inter_router_lsa
*)OSPF6_LSA_HEADER_END(
1079 ospf6_options_printbuf(router_lsa
->options
, buf
, sizeof(buf
));
1080 vty_out(vty
, " Options: %s%s", buf
, VNL
);
1081 vty_out(vty
, " Metric: %lu%s",
1082 (u_long
)OSPF6_ABR_SUMMARY_METRIC(router_lsa
), VNL
);
1084 inet_ntop(AF_INET
, &router_lsa
->router_id
, buf
, sizeof(buf
));
1085 vty_out(vty
, " Destination Router ID: %s%s", buf
, VNL
);
1090 /* Debug commands */
1091 DEFUN (debug_ospf6_abr
,
1092 debug_ospf6_abr_cmd
,
1096 "Debug OSPFv3 ABR function\n"
1099 OSPF6_DEBUG_ABR_ON();
1103 DEFUN (no_debug_ospf6_abr
,
1104 no_debug_ospf6_abr_cmd
,
1105 "no debug ospf6 abr",
1109 "Debug OSPFv3 ABR function\n"
1112 OSPF6_DEBUG_ABR_OFF();
1116 int config_write_ospf6_debug_abr(struct vty
*vty
)
1118 if (IS_OSPF6_DEBUG_ABR
)
1119 vty_out(vty
, "debug ospf6 abr%s", VNL
);
1123 void install_element_ospf6_debug_abr(void)
1125 install_element(ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1126 install_element(ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1127 install_element(CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1128 install_element(CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1131 struct ospf6_lsa_handler inter_prefix_handler
= {
1132 OSPF6_LSTYPE_INTER_PREFIX
,
1135 ospf6_inter_area_prefix_lsa_show
,
1136 ospf6_inter_area_prefix_lsa_get_prefix_str
,
1139 struct ospf6_lsa_handler inter_router_handler
= {
1140 OSPF6_LSTYPE_INTER_ROUTER
,
1143 ospf6_inter_area_router_lsa_show
,
1144 ospf6_inter_area_router_lsa_get_prefix_str
,
1147 void ospf6_abr_init(void)
1149 ospf6_install_lsa_handler(&inter_prefix_handler
);
1150 ospf6_install_lsa_handler(&inter_router_handler
);