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
;
56 ospf6_is_router_abr (struct ospf6
*o
)
58 struct listnode
*node
;
59 struct ospf6_area
*oa
;
62 for (ALL_LIST_ELEMENTS_RO (o
->area_list
, node
, oa
))
63 if (IS_AREA_ENABLED (oa
))
72 ospf6_abr_nexthops_belong_to_area (struct ospf6_route
*route
,
73 struct ospf6_area
*area
)
75 struct ospf6_interface
*oi
;
77 oi
= ospf6_interface_lookup_by_ifindex (ospf6_route_get_first_nh_index(route
));
78 if (oi
&& oi
->area
&& oi
->area
== area
)
85 ospf6_abr_delete_route (struct ospf6_route
*range
, struct ospf6_route
*summary
,
86 struct ospf6_route_table
*summary_table
,
87 struct ospf6_lsa
*old
)
91 ospf6_route_remove (summary
, summary_table
);
94 if (old
&& !OSPF6_LSA_IS_MAXAGE (old
))
95 ospf6_lsa_purge (old
);
99 ospf6_abr_enable_area (struct ospf6_area
*area
)
101 struct ospf6_area
*oa
;
102 struct listnode
*node
, *nnode
;
104 for (ALL_LIST_ELEMENTS (area
->ospf6
->area_list
, node
, nnode
, oa
))
105 /* update B bit for each area */
106 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
110 ospf6_abr_disable_area (struct ospf6_area
*area
)
112 struct ospf6_area
*oa
;
113 struct ospf6_route
*ro
, *nro
;
114 struct ospf6_lsa
*old
;
115 struct listnode
*node
, *nnode
;
117 /* Withdraw all summary prefixes previously originated */
118 for (ro
= ospf6_route_head (area
->summary_prefix
); ro
; ro
= nro
)
120 nro
= ospf6_route_next (ro
);
121 old
= ospf6_lsdb_lookup (ro
->path
.origin
.type
, ro
->path
.origin
.id
,
122 area
->ospf6
->router_id
, area
->lsdb
);
124 ospf6_lsa_purge (old
);
125 ospf6_route_remove (ro
, area
->summary_prefix
);
128 /* Withdraw all summary router-routes previously originated */
129 for (ro
= ospf6_route_head (area
->summary_router
); ro
; ro
= nro
)
131 nro
= ospf6_route_next (ro
);
132 old
= ospf6_lsdb_lookup (ro
->path
.origin
.type
, ro
->path
.origin
.id
,
133 area
->ospf6
->router_id
, area
->lsdb
);
135 ospf6_lsa_purge (old
);
136 ospf6_route_remove (ro
, area
->summary_router
);
139 /* Schedule Router-LSA for each area (ABR status may change) */
140 for (ALL_LIST_ELEMENTS (area
->ospf6
->area_list
, node
, nnode
, oa
))
141 /* update B bit for each area */
142 OSPF6_ROUTER_LSA_SCHEDULE (oa
);
145 /* RFC 2328 12.4.3. Summary-LSAs */
146 /* Returns 1 if a summary LSA has been generated for the area */
147 /* This is used by the area/range logic to add/remove blackhole routes */
149 ospf6_abr_originate_summary_to_area (struct ospf6_route
*route
,
150 struct ospf6_area
*area
)
152 struct ospf6_lsa
*lsa
, *old
= NULL
;
153 struct ospf6_route
*summary
, *range
= NULL
;
154 struct ospf6_area
*route_area
;
155 char buffer
[OSPF6_MAX_LSASIZE
];
156 struct ospf6_lsa_header
*lsa_header
;
158 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
159 struct ospf6_inter_router_lsa
*router_lsa
;
160 struct ospf6_route_table
*summary_table
= NULL
;
162 char buf
[PREFIX2STR_BUFFER
];
165 /* Only destination type network, range or ASBR are considered */
166 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
&&
167 route
->type
!= OSPF6_DEST_TYPE_RANGE
&&
168 ((route
->type
!= OSPF6_DEST_TYPE_ROUTER
) ||
169 !CHECK_FLAG (route
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)))
172 zlog_debug ("Route type is none of network, range nor ASBR, ignore");
176 /* AS External routes are never considered */
177 if (route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL1
||
178 route
->path
.type
== OSPF6_PATH_TYPE_EXTERNAL2
)
181 zlog_debug ("Path type is external, skip");
185 /* do not generate if the path's area is the same as target area */
186 if (route
->path
.area_id
== area
->area_id
)
189 zlog_debug ("The route is in the area itself, ignore");
193 /* do not generate if the nexthops belongs to the target area */
194 if (ospf6_abr_nexthops_belong_to_area (route
, area
))
197 zlog_debug ("The route's nexthop is in the same area, ignore");
201 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
203 if (ADV_ROUTER_IN_PREFIX (&route
->prefix
) == area
->ospf6
->router_id
)
205 inet_ntop (AF_INET
, &(ADV_ROUTER_IN_PREFIX (&route
->prefix
)), buf
,
207 zlog_debug ("%s: Skipping ASBR announcement for ABR (%s)", __func__
,
213 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
215 if (IS_OSPF6_DEBUG_ABR
|| IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER
))
218 inet_ntop (AF_INET
, &(ADV_ROUTER_IN_PREFIX (&route
->prefix
)),
220 zlog_debug ("Originating summary in area %s for ASBR %s",
223 summary_table
= area
->summary_router
;
227 if (IS_OSPF6_DEBUG_ABR
|| IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX
))
230 prefix2str (&route
->prefix
, buf
, sizeof (buf
));
231 zlog_debug ("Originating summary in area %s for %s",
234 summary_table
= area
->summary_prefix
;
237 summary
= ospf6_route_lookup (&route
->prefix
, summary_table
);
239 old
= ospf6_lsdb_lookup (summary
->path
.origin
.type
,
240 summary
->path
.origin
.id
,
241 area
->ospf6
->router_id
, area
->lsdb
);
243 /* if this route has just removed, remove corresponding LSA */
244 if (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_REMOVE
))
247 zlog_debug ("The route has just removed, purge previous LSA");
249 if (route
->type
== OSPF6_DEST_TYPE_RANGE
)
251 /* Whether the route have active longer prefix */
252 if (! CHECK_FLAG (route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
))
255 zlog_debug ("The range is not active. withdraw");
257 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
262 ospf6_lsa_purge (old
);
267 if ((route
->type
== OSPF6_DEST_TYPE_ROUTER
) && IS_AREA_STUB(area
))
270 zlog_debug ("Area has been stubbed, purge Inter-Router LSA");
272 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
276 if (area
->no_summary
&& (route
->path
.subtype
!= OSPF6_PATH_SUBTYPE_DEFAULT_RT
))
279 zlog_debug ("Area has been stubbed, purge prefix LSA");
281 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
285 /* do not generate if the route cost is greater or equal to LSInfinity */
286 if (route
->path
.cost
>= OSPF_LS_INFINITY
)
288 /* When we're clearing the range route because all active prefixes
289 * under the range are gone, we set the range's cost to
290 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
291 * don't want to trigger the code here for that. This code is for
292 * handling routes that have gone to infinity. The range removal happens
295 if ((route
->type
!= OSPF6_DEST_TYPE_RANGE
) &&
296 (route
->path
.cost
!= OSPF_AREA_RANGE_COST_UNSPEC
))
299 zlog_debug ("The cost exceeds LSInfinity, withdraw");
301 ospf6_lsa_purge (old
);
306 /* if this is a route to ASBR */
307 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
309 /* Only the prefered best path is considered */
310 if (! CHECK_FLAG (route
->flag
, OSPF6_ROUTE_BEST
))
313 zlog_debug ("This is the secondary path to the ASBR, ignore");
314 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
318 /* Do not generate if the area is stub */
322 /* if this is an intra-area route, this may be suppressed by aggregation */
323 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
&&
324 route
->path
.type
== OSPF6_PATH_TYPE_INTRA
)
326 /* search for configured address range for the route's area */
327 route_area
= ospf6_area_lookup (route
->path
.area_id
, area
->ospf6
);
329 range
= ospf6_route_lookup_bestmatch (&route
->prefix
,
330 route_area
->range_table
);
332 /* ranges are ignored when originate backbone routes to transit area.
333 Otherwise, if ranges are configured, the route is suppressed. */
334 if (range
&& ! CHECK_FLAG (range
->flag
, OSPF6_ROUTE_REMOVE
) &&
335 (route
->path
.area_id
!= OSPF_AREA_BACKBONE
||
336 ! IS_AREA_TRANSIT (area
)))
340 prefix2str (&range
->prefix
, buf
, sizeof (buf
));
341 zlog_debug ("Suppressed by range %s of area %s",
342 buf
, route_area
->name
);
344 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
349 /* If this is a configured address range */
350 if (route
->type
== OSPF6_DEST_TYPE_RANGE
)
352 /* If DoNotAdvertise is set */
353 if (CHECK_FLAG (route
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
))
356 zlog_debug ("This is the range with DoNotAdvertise set. ignore");
357 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
361 /* If there are no active prefixes in this range, remove */
362 if (! CHECK_FLAG (route
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
))
365 zlog_debug ("The range is not active. withdraw");
366 ospf6_abr_delete_route (route
, summary
, summary_table
, old
);
371 /* Check export list */
372 if (EXPORT_NAME (area
))
374 if (EXPORT_LIST (area
) == NULL
)
376 access_list_lookup (AFI_IP6
, EXPORT_NAME (area
));
378 if (EXPORT_LIST (area
))
379 if (access_list_apply (EXPORT_LIST (area
),
380 &route
->prefix
) == FILTER_DENY
)
384 inet_ntop (AF_INET
, &(ADV_ROUTER_IN_PREFIX (&route
->prefix
)),
386 zlog_debug ("prefix %s was denied by export list", buf
);
392 /* Check filter-list */
393 if (PREFIX_NAME_OUT (area
))
395 if (PREFIX_LIST_OUT (area
) == NULL
)
396 PREFIX_LIST_OUT (area
) =
397 prefix_list_lookup(AFI_IP6
, PREFIX_NAME_OUT (area
));
399 if (PREFIX_LIST_OUT (area
))
400 if (prefix_list_apply (PREFIX_LIST_OUT (area
),
401 &route
->prefix
) != PREFIX_PERMIT
)
405 inet_ntop (AF_INET
, &(ADV_ROUTER_IN_PREFIX (&route
->prefix
)),
407 zlog_debug ("prefix %s was denied by filter-list out", buf
);
413 /* the route is going to be originated. store it in area's summary_table */
416 summary
= ospf6_route_copy (route
);
417 summary
->path
.origin
.adv_router
= area
->ospf6
->router_id
;
419 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
421 summary
->path
.origin
.type
= htons (OSPF6_LSTYPE_INTER_ROUTER
);
422 summary
->path
.origin
.id
= ADV_ROUTER_IN_PREFIX (&route
->prefix
);
426 summary
->path
.origin
.type
= htons (OSPF6_LSTYPE_INTER_PREFIX
);
427 summary
->path
.origin
.id
=
428 ospf6_new_ls_id (summary
->path
.origin
.type
,
429 summary
->path
.origin
.adv_router
, area
->lsdb
);
431 summary
= ospf6_route_add (summary
, summary_table
);
435 summary
->type
= route
->type
;
436 monotime(&summary
->changed
);
439 summary
->path
.router_bits
= route
->path
.router_bits
;
440 summary
->path
.options
[0] = route
->path
.options
[0];
441 summary
->path
.options
[1] = route
->path
.options
[1];
442 summary
->path
.options
[2] = route
->path
.options
[2];
443 summary
->path
.prefix_options
= route
->path
.prefix_options
;
444 summary
->path
.area_id
= area
->area_id
;
445 summary
->path
.type
= OSPF6_PATH_TYPE_INTER
;
446 summary
->path
.subtype
= route
->path
.subtype
;
447 summary
->path
.cost
= route
->path
.cost
;
448 /* summary->nexthop[0] = route->nexthop[0]; */
451 memset (buffer
, 0, sizeof (buffer
));
452 lsa_header
= (struct ospf6_lsa_header
*) buffer
;
454 if (route
->type
== OSPF6_DEST_TYPE_ROUTER
)
456 router_lsa
= (struct ospf6_inter_router_lsa
*)
457 ((caddr_t
) lsa_header
+ sizeof (struct ospf6_lsa_header
));
458 p
= (caddr_t
) router_lsa
+ sizeof (struct ospf6_inter_router_lsa
);
460 /* Fill Inter-Area-Router-LSA */
461 router_lsa
->options
[0] = route
->path
.options
[0];
462 router_lsa
->options
[1] = route
->path
.options
[1];
463 router_lsa
->options
[2] = route
->path
.options
[2];
464 OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa
, route
->path
.cost
);
465 router_lsa
->router_id
= ADV_ROUTER_IN_PREFIX (&route
->prefix
);
466 type
= htons (OSPF6_LSTYPE_INTER_ROUTER
);
470 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)
471 ((caddr_t
) lsa_header
+ sizeof (struct ospf6_lsa_header
));
472 p
= (caddr_t
) prefix_lsa
+ sizeof (struct ospf6_inter_prefix_lsa
);
474 /* Fill Inter-Area-Prefix-LSA */
475 OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa
, route
->path
.cost
);
476 prefix_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
477 prefix_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
480 memcpy (p
, &route
->prefix
.u
.prefix6
,
481 OSPF6_PREFIX_SPACE (route
->prefix
.prefixlen
));
482 ospf6_prefix_apply_mask (&prefix_lsa
->prefix
);
483 p
+= OSPF6_PREFIX_SPACE (route
->prefix
.prefixlen
);
484 type
= htons (OSPF6_LSTYPE_INTER_PREFIX
);
487 /* Fill LSA Header */
489 lsa_header
->type
= type
;
490 lsa_header
->id
= summary
->path
.origin
.id
;
491 lsa_header
->adv_router
= area
->ospf6
->router_id
;
493 ospf6_new_ls_seqnum (lsa_header
->type
, lsa_header
->id
,
494 lsa_header
->adv_router
, area
->lsdb
);
495 lsa_header
->length
= htons ((caddr_t
) p
- (caddr_t
) lsa_header
);
498 ospf6_lsa_checksum (lsa_header
);
501 lsa
= ospf6_lsa_create (lsa_header
);
504 ospf6_lsa_originate_area (lsa
, area
);
510 ospf6_abr_range_reset_cost (struct ospf6
*ospf6
)
512 struct listnode
*node
, *nnode
;
513 struct ospf6_area
*oa
;
514 struct ospf6_route
*range
;
516 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, node
, nnode
, oa
))
517 for (range
= ospf6_route_head (oa
->range_table
); range
;
518 range
= ospf6_route_next (range
))
519 OSPF6_ABR_RANGE_CLEAR_COST(range
);
522 static inline u_int32_t
523 ospf6_abr_range_compute_cost (struct ospf6_route
*range
, struct ospf6
*o
)
525 struct ospf6_route
*ro
;
528 for (ro
= ospf6_route_match_head (&range
->prefix
, o
->route_table
);
529 ro
; ro
= ospf6_route_match_next (&range
->prefix
, ro
))
531 if (ro
->path
.area_id
== range
->path
.area_id
&&
532 (ro
->path
.type
== OSPF6_PATH_TYPE_INTRA
) &&
533 ! CHECK_FLAG (ro
->flag
, OSPF6_ROUTE_REMOVE
))
534 cost
= MAX (cost
, ro
->path
.cost
);
541 ospf6_abr_range_summary_needs_update (struct ospf6_route
*range
,
544 int redo_summary
= 0;
546 if (CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
))
548 UNSET_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
551 else if (CHECK_FLAG (range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
))
553 if (range
->path
.cost
!= 0)
555 range
->path
.cost
= 0;
561 if ((OSPF6_PATH_COST_IS_CONFIGURED(range
->path
) &&
562 range
->path
.cost
!= range
->path
.u
.cost_config
))
564 range
->path
.cost
= range
->path
.u
.cost_config
;
565 SET_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
568 else if (!OSPF6_PATH_COST_IS_CONFIGURED(range
->path
) &&
569 range
->path
.cost
!= cost
)
571 range
->path
.cost
= cost
;
572 SET_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
576 else if (CHECK_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
))
578 /* Cost is zero, meaning no active range */
579 UNSET_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
);
580 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
584 return (redo_summary
);
588 ospf6_abr_range_update (struct ospf6_route
*range
)
591 struct listnode
*node
, *nnode
;
592 struct ospf6_area
*oa
;
593 int summary_orig
= 0;
595 assert (range
->type
== OSPF6_DEST_TYPE_RANGE
);
597 /* update range's cost and active flag */
598 cost
= ospf6_abr_range_compute_cost (range
, ospf6
);
600 /* Non-zero cost is a proxy for active longer prefixes in this range.
601 * If there are active routes covered by this range AND either the configured
602 * cost has changed or the summarized cost has changed then redo summaries.
603 * Alternately, if there are no longer active prefixes and there are
604 * summary announcements, withdraw those announcements.
606 * The don't advertise code relies on the path.cost being set to UNSPEC to
607 * work the first time. Subsequent times the path.cost is not 0 anyway if there
608 * were active ranges.
611 if (ospf6_abr_range_summary_needs_update (range
, cost
))
613 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, node
, nnode
, oa
))
614 summary_orig
+= ospf6_abr_originate_summary_to_area (range
, oa
);
616 if (CHECK_FLAG (range
->flag
, OSPF6_ROUTE_ACTIVE_SUMMARY
) && summary_orig
)
618 if (! CHECK_FLAG (range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
))
620 if (IS_OSPF6_DEBUG_ABR
)
621 zlog_debug ("Add discard route");
623 ospf6_zebra_add_discard (range
);
628 /* Summary removed or no summary generated as no specifics exist */
629 if (CHECK_FLAG (range
->flag
, OSPF6_ROUTE_BLACKHOLE_ADDED
))
631 if (IS_OSPF6_DEBUG_ABR
)
632 zlog_debug ("Delete discard route");
634 ospf6_zebra_delete_discard (range
);
641 ospf6_abr_originate_summary (struct ospf6_route
*route
)
643 struct listnode
*node
, *nnode
;
644 struct ospf6_area
*oa
;
645 struct ospf6_route
*range
= NULL
;
647 if (route
->type
== OSPF6_DEST_TYPE_NETWORK
)
649 oa
= ospf6_area_lookup (route
->path
.area_id
, ospf6
);
650 range
= ospf6_route_lookup_bestmatch (&route
->prefix
, oa
->range_table
);
653 ospf6_abr_range_update (range
);
657 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, node
, nnode
, oa
))
658 ospf6_abr_originate_summary_to_area (route
, oa
);
662 ospf6_abr_defaults_to_stub (struct ospf6
*o
)
664 struct listnode
*node
, *nnode
;
665 struct ospf6_area
*oa
;
666 struct ospf6_route
*def
, *route
;
671 def
= ospf6_route_create();
672 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
673 def
->prefix
.family
= AF_INET6
;
674 def
->prefix
.prefixlen
= 0;
675 memset (&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
676 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
677 def
->path
.type
= OSPF6_PATH_TYPE_INTER
;
678 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
679 def
->path
.area_id
= o
->backbone
->area_id
;
681 for (ALL_LIST_ELEMENTS (ospf6
->area_list
, node
, nnode
, oa
))
683 if (!IS_AREA_STUB (oa
))
685 /* withdraw defaults when an area switches from stub to non-stub */
686 route
= ospf6_route_lookup (&def
->prefix
, oa
->summary_prefix
);
687 if (route
&& (route
->path
.subtype
== def
->path
.subtype
))
689 if (IS_OSPF6_DEBUG_ABR
)
690 zlog_debug ("Withdrawing default route from non-stubby area %s",
692 SET_FLAG (def
->flag
, OSPF6_ROUTE_REMOVE
);
693 ospf6_abr_originate_summary_to_area (def
, oa
);
698 /* announce defaults to stubby areas */
699 if (IS_OSPF6_DEBUG_ABR
)
700 zlog_debug ("Announcing default route into stubby area %s",
702 UNSET_FLAG (def
->flag
, OSPF6_ROUTE_REMOVE
);
703 ospf6_abr_originate_summary_to_area (def
, oa
);
706 ospf6_route_delete (def
);
709 /* RFC 2328 16.2. Calculating the inter-area routes */
711 ospf6_abr_examin_summary (struct ospf6_lsa
*lsa
, struct ospf6_area
*oa
)
713 struct prefix prefix
, abr_prefix
;
714 struct ospf6_route_table
*table
= NULL
;
715 struct ospf6_route
*range
, *route
, *old
= NULL
;
716 struct ospf6_route
*abr_entry
;
718 char options
[3] = {0, 0, 0};
719 u_int8_t prefix_options
= 0;
721 u_char router_bits
= 0;
722 char buf
[PREFIX2STR_BUFFER
];
724 struct ospf6_inter_prefix_lsa
*prefix_lsa
= NULL
;
725 struct ospf6_inter_router_lsa
*router_lsa
= NULL
;
727 memset (&prefix
, 0, sizeof (prefix
));
729 if (lsa
->header
->type
== htons (OSPF6_LSTYPE_INTER_PREFIX
))
731 if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX
))
734 zlog_debug ("Examin %s in area %s", lsa
->name
, oa
->name
);
737 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)
738 OSPF6_LSA_HEADER_END (lsa
->header
);
739 prefix
.family
= AF_INET6
;
740 prefix
.prefixlen
= prefix_lsa
->prefix
.prefix_length
;
741 ospf6_prefix_in6_addr (&prefix
.u
.prefix6
, &prefix_lsa
->prefix
);
743 prefix2str (&prefix
, buf
, sizeof (buf
));
744 table
= oa
->ospf6
->route_table
;
745 type
= OSPF6_DEST_TYPE_NETWORK
;
746 prefix_options
= prefix_lsa
->prefix
.prefix_options
;
747 cost
= OSPF6_ABR_SUMMARY_METRIC (prefix_lsa
);
749 else if (lsa
->header
->type
== htons (OSPF6_LSTYPE_INTER_ROUTER
))
751 if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER
))
754 zlog_debug ("Examin %s in area %s", lsa
->name
, oa
->name
);
757 router_lsa
= (struct ospf6_inter_router_lsa
*)
758 OSPF6_LSA_HEADER_END (lsa
->header
);
759 ospf6_linkstate_prefix (router_lsa
->router_id
, htonl (0), &prefix
);
761 inet_ntop (AF_INET
, &router_lsa
->router_id
, buf
, sizeof (buf
));
763 table
= oa
->ospf6
->brouter_table
;
764 type
= OSPF6_DEST_TYPE_ROUTER
;
765 options
[0] = router_lsa
->options
[0];
766 options
[1] = router_lsa
->options
[1];
767 options
[2] = router_lsa
->options
[2];
768 cost
= OSPF6_ABR_SUMMARY_METRIC (router_lsa
);
769 SET_FLAG (router_bits
, OSPF6_ROUTER_BIT_E
);
774 /* Find existing route */
775 route
= ospf6_route_lookup (&prefix
, table
);
777 ospf6_route_lock (route
);
778 while (route
&& ospf6_route_is_prefix (&prefix
, route
))
780 if (route
->path
.area_id
== oa
->area_id
&&
781 route
->path
.origin
.type
== lsa
->header
->type
&&
782 route
->path
.origin
.id
== lsa
->header
->id
&&
783 route
->path
.origin
.adv_router
== lsa
->header
->adv_router
&&
784 ! CHECK_FLAG (route
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
786 route
= ospf6_route_next (route
);
789 ospf6_route_unlock (route
);
791 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
792 if (cost
== OSPF_LS_INFINITY
)
795 zlog_debug ("cost is LS_INFINITY, ignore");
797 ospf6_route_remove (old
, table
);
800 if (OSPF6_LSA_IS_MAXAGE (lsa
))
803 zlog_debug ("LSA is MaxAge, ignore");
805 ospf6_route_remove (old
, table
);
809 /* (2) if the LSA is self-originated, ignore */
810 if (lsa
->header
->adv_router
== oa
->ospf6
->router_id
)
813 zlog_debug ("LSA is self-originated, ignore");
815 ospf6_route_remove (old
, table
);
819 /* (3) if the prefix is equal to an active configured address range */
820 /* or if the NU bit is set in the prefix */
821 if (lsa
->header
->type
== htons (OSPF6_LSTYPE_INTER_PREFIX
))
823 range
= ospf6_route_lookup (&prefix
, oa
->range_table
);
827 zlog_debug ("Prefix is equal to address range, ignore");
829 ospf6_route_remove (old
, table
);
833 if (CHECK_FLAG (prefix_lsa
->prefix
.prefix_options
,
834 OSPF6_PREFIX_OPTION_NU
) ||
835 CHECK_FLAG (prefix_lsa
->prefix
.prefix_options
,
836 OSPF6_PREFIX_OPTION_LA
))
839 zlog_debug ("Prefix has NU/LA bit set, ignore");
841 ospf6_route_remove (old
, table
);
846 if (lsa
->header
->type
== htons (OSPF6_LSTYPE_INTER_ROUTER
))
848 /* To pass test suites */
849 if (! OSPF6_OPT_ISSET (router_lsa
->options
, OSPF6_OPT_R
) ||
850 ! OSPF6_OPT_ISSET (router_lsa
->options
, OSPF6_OPT_V6
))
853 zlog_debug ("Prefix has NU/LA bit set, ignore");
855 ospf6_route_remove (old
, table
);
859 /* Avoid infinite recursion if someone has maliciously announced an
860 Inter-Router LSA for an ABR
862 if (lsa
->header
->adv_router
== router_lsa
->router_id
)
865 zlog_debug ("Ignorning Inter-Router LSA for an ABR (%s)",
868 ospf6_route_remove (old
, table
);
874 /* (4) if the routing table entry for the ABR does not exist */
875 ospf6_linkstate_prefix (lsa
->header
->adv_router
, htonl (0), &abr_prefix
);
876 abr_entry
= ospf6_route_lookup (&abr_prefix
, oa
->ospf6
->brouter_table
);
877 if (abr_entry
== NULL
|| abr_entry
->path
.area_id
!= oa
->area_id
||
878 CHECK_FLAG (abr_entry
->flag
, OSPF6_ROUTE_REMOVE
) ||
879 ! CHECK_FLAG (abr_entry
->path
.router_bits
, OSPF6_ROUTER_BIT_B
))
882 zlog_debug ("ABR router entry does not exist, ignore");
884 ospf6_route_remove (old
, table
);
888 /* Check import list */
889 if (IMPORT_NAME (oa
))
891 if (IMPORT_LIST (oa
) == NULL
)
892 IMPORT_LIST (oa
) = access_list_lookup (AFI_IP6
, IMPORT_NAME (oa
));
894 if (IMPORT_LIST (oa
))
895 if (access_list_apply (IMPORT_LIST (oa
), &prefix
) == FILTER_DENY
)
898 zlog_debug ("Prefix was denied by import-list");
900 ospf6_route_remove (old
, table
);
905 /* Check input prefix-list */
906 if (PREFIX_NAME_IN (oa
))
908 if (PREFIX_LIST_IN (oa
) == NULL
)
909 PREFIX_LIST_IN (oa
) = prefix_list_lookup (AFI_IP6
, PREFIX_NAME_IN (oa
));
911 if (PREFIX_LIST_IN (oa
))
912 if (prefix_list_apply (PREFIX_LIST_IN (oa
), &prefix
) != PREFIX_PERMIT
)
915 zlog_debug ("Prefix was denied by prefix-list");
917 ospf6_route_remove (old
, table
);
922 /* (5),(6): the path preference is handled by the sorting
923 in the routing table. Always install the path by substituting
924 old route (if any). */
926 route
= ospf6_route_copy (old
);
928 route
= ospf6_route_create ();
931 route
->prefix
= prefix
;
932 route
->path
.origin
.type
= lsa
->header
->type
;
933 route
->path
.origin
.id
= lsa
->header
->id
;
934 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
935 route
->path
.router_bits
= router_bits
;
936 route
->path
.options
[0] = options
[0];
937 route
->path
.options
[1] = options
[1];
938 route
->path
.options
[2] = options
[2];
939 route
->path
.prefix_options
= prefix_options
;
940 route
->path
.area_id
= oa
->area_id
;
941 route
->path
.type
= OSPF6_PATH_TYPE_INTER
;
942 route
->path
.cost
= abr_entry
->path
.cost
+ cost
;
944 ospf6_route_copy_nexthops (route
, abr_entry
);
946 /* (7) If the routes are identical, copy the next hops over to existing
947 route. ospf6's route table implementation will otherwise string both
948 routes, but keep the older one as the best route since the routes
951 old
= ospf6_route_lookup (&prefix
, table
);
953 if (old
&& (ospf6_route_cmp (route
, old
) == 0))
955 ospf6_route_merge_nexthops (old
, route
);
958 (*table
->hook_add
) (old
);
960 /* Delete new route */
961 ospf6_route_delete (route
);
966 zlog_debug ("Install route: %s", buf
);
967 /* ospf6_ia_add_nw_route (table, &prefix, route); */
968 ospf6_route_add (route
, table
);
973 ospf6_abr_examin_brouter (u_int32_t router_id
)
975 struct ospf6_lsa
*lsa
;
976 struct ospf6_area
*oa
;
979 if (ospf6_is_router_abr (ospf6
))
980 oa
= ospf6
->backbone
;
982 oa
= listgetdata(listhead(ospf6
->area_list
));
985 * It is possible to designate a non backbone
986 * area first. If that is the case safely
987 * fall out of this function.
992 type
= htons (OSPF6_LSTYPE_INTER_ROUTER
);
993 for (lsa
= ospf6_lsdb_type_router_head (type
, router_id
, oa
->lsdb
); lsa
;
994 lsa
= ospf6_lsdb_type_router_next (type
, router_id
, lsa
))
995 ospf6_abr_examin_summary (lsa
, oa
);
997 type
= htons (OSPF6_LSTYPE_INTER_PREFIX
);
998 for (lsa
= ospf6_lsdb_type_router_head (type
, router_id
, oa
->lsdb
); lsa
;
999 lsa
= ospf6_lsdb_type_router_next (type
, router_id
, lsa
))
1000 ospf6_abr_examin_summary (lsa
, oa
);
1004 ospf6_abr_reimport (struct ospf6_area
*oa
)
1006 struct ospf6_lsa
*lsa
;
1009 type
= htons (OSPF6_LSTYPE_INTER_ROUTER
);
1010 for (lsa
= ospf6_lsdb_type_head (type
, oa
->lsdb
); lsa
;
1011 lsa
= ospf6_lsdb_type_next (type
, lsa
))
1012 ospf6_abr_examin_summary (lsa
, oa
);
1014 type
= htons (OSPF6_LSTYPE_INTER_PREFIX
);
1015 for (lsa
= ospf6_lsdb_type_head (type
, oa
->lsdb
); lsa
;
1016 lsa
= ospf6_lsdb_type_next (type
, lsa
))
1017 ospf6_abr_examin_summary (lsa
, oa
);
1021 ospf6_abr_prefix_resummarize (struct ospf6
*o
)
1023 struct ospf6_route
*route
;
1025 if (IS_OSPF6_DEBUG_ABR
)
1026 zlog_debug ("Re-examining Inter-Prefix Summaries");
1028 for (route
= ospf6_route_head (o
->route_table
); route
;
1029 route
= ospf6_route_next (route
))
1030 ospf6_abr_originate_summary(route
);
1032 if (IS_OSPF6_DEBUG_ABR
)
1033 zlog_debug ("Finished re-examining Inter-Prefix Summaries");
1037 /* Display functions */
1039 ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa
*lsa
, char *buf
,
1040 int buflen
, int pos
)
1042 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1043 struct in6_addr in6
;
1047 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)
1048 OSPF6_LSA_HEADER_END (lsa
->header
);
1050 ospf6_prefix_in6_addr (&in6
, &prefix_lsa
->prefix
);
1053 inet_ntop (AF_INET6
, &in6
, buf
, buflen
);
1054 sprintf (&buf
[strlen(buf
)], "/%d", prefix_lsa
->prefix
.prefix_length
);
1062 ospf6_inter_area_prefix_lsa_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
1064 struct ospf6_inter_prefix_lsa
*prefix_lsa
;
1065 char buf
[INET6_ADDRSTRLEN
];
1067 prefix_lsa
= (struct ospf6_inter_prefix_lsa
*)
1068 OSPF6_LSA_HEADER_END (lsa
->header
);
1070 vty_out (vty
, " Metric: %lu%s",
1071 (u_long
) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa
), VNL
);
1073 ospf6_prefix_options_printbuf (prefix_lsa
->prefix
.prefix_options
,
1075 vty_out (vty
, " Prefix Options: %s%s", buf
, VNL
);
1077 vty_out (vty
, " Prefix: %s%s",
1078 ospf6_inter_area_prefix_lsa_get_prefix_str (lsa
, buf
, sizeof(buf
),
1085 ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa
*lsa
, char *buf
,
1086 int buflen
, int pos
)
1088 struct ospf6_inter_router_lsa
*router_lsa
;
1092 router_lsa
= (struct ospf6_inter_router_lsa
*)
1093 OSPF6_LSA_HEADER_END (lsa
->header
);
1097 inet_ntop (AF_INET
, &router_lsa
->router_id
, buf
, buflen
);
1104 ospf6_inter_area_router_lsa_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
1106 struct ospf6_inter_router_lsa
*router_lsa
;
1109 router_lsa
= (struct ospf6_inter_router_lsa
*)
1110 OSPF6_LSA_HEADER_END (lsa
->header
);
1112 ospf6_options_printbuf (router_lsa
->options
, buf
, sizeof (buf
));
1113 vty_out (vty
, " Options: %s%s", buf
, VNL
);
1114 vty_out (vty
, " Metric: %lu%s",
1115 (u_long
) OSPF6_ABR_SUMMARY_METRIC (router_lsa
), VNL
);
1117 inet_ntop (AF_INET
, &router_lsa
->router_id
, buf
, sizeof (buf
));
1118 vty_out (vty
, " Destination Router ID: %s%s", buf
, VNL
);
1123 /* Debug commands */
1124 DEFUN (debug_ospf6_abr
,
1125 debug_ospf6_abr_cmd
,
1129 "Debug OSPFv3 ABR function\n"
1132 OSPF6_DEBUG_ABR_ON ();
1136 DEFUN (no_debug_ospf6_abr
,
1137 no_debug_ospf6_abr_cmd
,
1138 "no debug ospf6 abr",
1142 "Debug OSPFv3 ABR function\n"
1145 OSPF6_DEBUG_ABR_OFF ();
1150 config_write_ospf6_debug_abr (struct vty
*vty
)
1152 if (IS_OSPF6_DEBUG_ABR
)
1153 vty_out (vty
, "debug ospf6 abr%s", VNL
);
1158 install_element_ospf6_debug_abr (void)
1160 install_element (ENABLE_NODE
, &debug_ospf6_abr_cmd
);
1161 install_element (ENABLE_NODE
, &no_debug_ospf6_abr_cmd
);
1162 install_element (CONFIG_NODE
, &debug_ospf6_abr_cmd
);
1163 install_element (CONFIG_NODE
, &no_debug_ospf6_abr_cmd
);
1166 struct ospf6_lsa_handler inter_prefix_handler
=
1168 OSPF6_LSTYPE_INTER_PREFIX
,
1171 ospf6_inter_area_prefix_lsa_show
,
1172 ospf6_inter_area_prefix_lsa_get_prefix_str
,
1175 struct ospf6_lsa_handler inter_router_handler
=
1177 OSPF6_LSTYPE_INTER_ROUTER
,
1180 ospf6_inter_area_router_lsa_show
,
1181 ospf6_inter_area_router_lsa_get_prefix_str
,
1185 ospf6_abr_init (void)
1187 ospf6_install_lsa_handler (&inter_prefix_handler
);
1188 ospf6_install_lsa_handler (&inter_router_handler
);