]>
git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ia.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * OSPF inter-area routing.
4 * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
18 #include "ospfd/ospfd.h"
19 #include "ospfd/ospf_interface.h"
20 #include "ospfd/ospf_ism.h"
21 #include "ospfd/ospf_asbr.h"
22 #include "ospfd/ospf_lsa.h"
23 #include "ospfd/ospf_lsdb.h"
24 #include "ospfd/ospf_neighbor.h"
25 #include "ospfd/ospf_nsm.h"
26 #include "ospfd/ospf_spf.h"
27 #include "ospfd/ospf_route.h"
28 #include "ospfd/ospf_ase.h"
29 #include "ospfd/ospf_abr.h"
30 #include "ospfd/ospf_ia.h"
31 #include "ospfd/ospf_dump.h"
33 static struct ospf_route
*ospf_find_abr_route(struct route_table
*rtrs
,
34 struct prefix_ipv4
*abr
,
35 struct ospf_area
*area
)
37 struct route_node
*rn
;
38 struct ospf_route
* or ;
39 struct listnode
*node
;
41 if ((rn
= route_node_lookup(rtrs
, (struct prefix
*)abr
)) == NULL
)
44 route_unlock_node(rn
);
46 for (ALL_LIST_ELEMENTS_RO((struct list
*)rn
->info
, node
, or))
47 if (IPV4_ADDR_SAME(& or->u
.std
.area_id
, &area
->area_id
)
48 && (or->u
.std
.flags
& ROUTER_LSA_BORDER
))
54 static void ospf_ia_network_route(struct ospf
*ospf
, struct route_table
*rt
,
55 struct prefix_ipv4
*p
,
56 struct ospf_route
*new_or
,
57 struct ospf_route
*abr_or
)
59 struct route_node
*rn1
;
60 struct ospf_route
* or ;
62 if (IS_DEBUG_OSPF_EVENT
)
63 zlog_debug("%s: processing summary route to %pFX", __func__
, p
);
65 /* Find a route to the same dest */
66 if ((rn1
= route_node_lookup(rt
, (struct prefix
*)p
))) {
69 route_unlock_node(rn1
);
71 if ((or = rn1
->info
)) {
72 if (IS_DEBUG_OSPF_EVENT
)
74 "%s: Found a route to the same network",
76 /* Check the existing route. */
77 if ((res
= ospf_route_cmp(ospf
, new_or
, or)) < 0) {
78 /* New route is better, so replace old one. */
79 ospf_route_subst(rn1
, new_or
, abr_or
);
80 } else if (res
== 0) {
81 /* New and old route are equal, so next hops can
84 ospf_route_copy_nexthops(or, abr_or
->paths
);
85 route_unlock_node(rn1
);
87 /* new route can be deleted, because existing
88 * route has been updated. */
89 ospf_route_free(new_or
);
91 /* New route is worse, so free it. */
92 ospf_route_free(new_or
);
98 if (IS_DEBUG_OSPF_EVENT
)
99 zlog_debug("%s: add new route to %pFX", __func__
, p
);
100 ospf_route_add(rt
, p
, new_or
, abr_or
);
104 static void ospf_ia_router_route(struct ospf
*ospf
, struct route_table
*rtrs
,
105 struct prefix_ipv4
*p
,
106 struct ospf_route
*new_or
,
107 struct ospf_route
*abr_or
)
109 struct ospf_route
* or = NULL
;
110 struct route_node
*rn
;
113 if (IS_DEBUG_OSPF_EVENT
)
114 zlog_debug("%s: considering %pFX", __func__
, p
);
116 /* Find a route to the same dest */
117 rn
= route_node_get(rtrs
, (struct prefix
*)p
);
119 if (rn
->info
== NULL
)
120 /* This is a new route */
121 rn
->info
= list_new();
123 struct ospf_area
*or_area
;
124 or_area
= ospf_area_lookup_by_area_id(ospf
,
125 new_or
->u
.std
.area_id
);
127 /* This is an additional route */
128 route_unlock_node(rn
);
129 or = ospf_find_asbr_route_through_area(rtrs
, p
, or_area
);
133 if (IS_DEBUG_OSPF_EVENT
)
135 "%s: a route to the same ABR through the same area exists",
137 /* New route is better */
138 if ((ret
= ospf_route_cmp(ospf
, new_or
, or)) < 0) {
139 listnode_delete(rn
->info
, or);
143 /* Routes are the same */
145 if (IS_DEBUG_OSPF_EVENT
)
146 zlog_debug("%s: merging the new route",
149 ospf_route_copy_nexthops(or, abr_or
->paths
);
150 ospf_route_free(new_or
);
153 /* New route is worse */
155 if (IS_DEBUG_OSPF_EVENT
)
156 zlog_debug("%s: skipping the new route",
158 ospf_route_free(new_or
);
163 ospf_route_copy_nexthops(new_or
, abr_or
->paths
);
165 if (IS_DEBUG_OSPF_EVENT
)
166 zlog_debug("%s: adding the new route", __func__
);
168 listnode_add(rn
->info
, new_or
);
172 static int process_summary_lsa(struct ospf_area
*area
, struct route_table
*rt
,
173 struct route_table
*rtrs
, struct ospf_lsa
*lsa
)
175 struct ospf
*ospf
= area
->ospf
;
176 struct ospf_area_range
*range
;
177 struct ospf_route
*abr_or
, *new_or
;
178 struct summary_lsa
*sl
;
179 struct prefix_ipv4 p
, abr
;
185 sl
= (struct summary_lsa
*)lsa
->data
;
187 if (IS_DEBUG_OSPF_EVENT
)
188 zlog_debug("%s: LS ID: %pI4", __func__
, &sl
->header
.id
);
190 metric
= GET_METRIC(sl
->metric
);
192 if (metric
== OSPF_LS_INFINITY
)
195 if (IS_LSA_MAXAGE(lsa
))
198 if (ospf_lsa_is_self_originated(area
->ospf
, lsa
))
202 p
.prefix
= sl
->header
.id
;
204 if (sl
->header
.type
== OSPF_SUMMARY_LSA
)
205 p
.prefixlen
= ip_masklen(sl
->mask
);
207 p
.prefixlen
= IPV4_MAX_BITLEN
;
211 if (sl
->header
.type
== OSPF_SUMMARY_LSA
212 && (range
= ospf_area_range_match_any(ospf
, &p
))
213 && ospf_area_range_active(range
))
216 /* XXX: This check seems dubious to me. If an ABR has already decided
217 * to consider summaries received in this area, then why would one wish
218 * to exclude default?
220 if (IS_OSPF_ABR(ospf
) && ospf
->abr_type
!= OSPF_ABR_STAND
221 && area
->external_routing
!= OSPF_AREA_DEFAULT
222 && p
.prefix
.s_addr
== OSPF_DEFAULT_DESTINATION
&& p
.prefixlen
== 0)
223 return 0; /* Ignore summary default from a stub area */
225 abr
.family
= AF_INET
;
226 abr
.prefix
= sl
->header
.adv_router
;
227 abr
.prefixlen
= IPV4_MAX_BITLEN
;
228 apply_mask_ipv4(&abr
);
230 abr_or
= ospf_find_abr_route(rtrs
, &abr
, area
);
235 new_or
= ospf_route_new();
236 new_or
->type
= OSPF_DESTINATION_NETWORK
;
237 new_or
->id
= sl
->header
.id
;
238 new_or
->mask
= sl
->mask
;
239 new_or
->u
.std
.options
= sl
->header
.options
;
240 new_or
->u
.std
.origin
= (struct lsa_header
*)sl
;
241 new_or
->cost
= abr_or
->cost
+ metric
;
242 new_or
->u
.std
.area_id
= area
->area_id
;
243 new_or
->u
.std
.external_routing
= area
->external_routing
;
244 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
246 if (sl
->header
.type
== OSPF_SUMMARY_LSA
)
247 ospf_ia_network_route(ospf
, rt
, &p
, new_or
, abr_or
);
249 new_or
->type
= OSPF_DESTINATION_ROUTER
;
250 new_or
->u
.std
.flags
= ROUTER_LSA_EXTERNAL
;
251 ospf_ia_router_route(ospf
, rtrs
, &p
, new_or
, abr_or
);
257 static void ospf_examine_summaries(struct ospf_area
*area
,
258 struct route_table
*lsdb_rt
,
259 struct route_table
*rt
,
260 struct route_table
*rtrs
)
262 struct ospf_lsa
*lsa
;
263 struct route_node
*rn
;
265 LSDB_LOOP (lsdb_rt
, rn
, lsa
)
266 process_summary_lsa(area
, rt
, rtrs
, lsa
);
269 int ospf_area_is_transit(struct ospf_area
*area
)
271 return (area
->transit
== OSPF_TRANSIT_TRUE
)
272 || ospf_full_virtual_nbrs(
273 area
); /* Cisco forgets to set the V-bit :( */
276 static void ospf_update_network_route(struct ospf
*ospf
, struct route_table
*rt
,
277 struct route_table
*rtrs
,
278 struct summary_lsa
*lsa
,
279 struct prefix_ipv4
*p
,
280 struct ospf_area
*area
)
282 struct route_node
*rn
;
283 struct ospf_route
* or, *abr_or
, *new_or
;
284 struct prefix_ipv4 abr
;
287 abr
.family
= AF_INET
;
288 abr
.prefix
= lsa
->header
.adv_router
;
289 abr
.prefixlen
= IPV4_MAX_BITLEN
;
290 apply_mask_ipv4(&abr
);
292 abr_or
= ospf_find_abr_route(rtrs
, &abr
, area
);
294 if (abr_or
== NULL
) {
295 if (IS_DEBUG_OSPF_EVENT
)
296 zlog_debug("%s: can't find a route to the ABR",
301 cost
= abr_or
->cost
+ GET_METRIC(lsa
->metric
);
303 rn
= route_node_lookup(rt
, (struct prefix
*)p
);
306 if (ospf
->abr_type
!= OSPF_ABR_SHORTCUT
)
307 return; /* Standard ABR can update only already
310 if (IS_DEBUG_OSPF_EVENT
)
311 zlog_debug("%s: Allowing Shortcut ABR to add new route",
313 new_or
= ospf_route_new();
314 new_or
->type
= OSPF_DESTINATION_NETWORK
;
315 new_or
->id
= lsa
->header
.id
;
316 new_or
->mask
= lsa
->mask
;
317 new_or
->u
.std
.options
= lsa
->header
.options
;
318 new_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
320 new_or
->u
.std
.area_id
= area
->area_id
;
321 new_or
->u
.std
.external_routing
= area
->external_routing
;
322 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
323 ospf_route_add(rt
, p
, new_or
, abr_or
);
327 route_unlock_node(rn
);
328 if (rn
->info
== NULL
)
334 if (or->path_type
!= OSPF_PATH_INTRA_AREA
&&
335 or->path_type
!= OSPF_PATH_INTER_AREA
) {
336 if (IS_DEBUG_OSPF_EVENT
)
337 zlog_debug("%s: ERR: path type is wrong", __func__
);
341 if (ospf
->abr_type
== OSPF_ABR_SHORTCUT
) {
343 or->path_type
== OSPF_PATH_INTRA_AREA
344 && !OSPF_IS_AREA_ID_BACKBONE(
345 or->u
.std
.area_id
)) {
346 if (IS_DEBUG_OSPF_EVENT
)
348 "%s: Shortcut: this intra-area path is not backbone",
352 } else /* Not Shortcut ABR */
354 if (!OSPF_IS_AREA_ID_BACKBONE(or->u
.std
.area_id
)) {
355 if (IS_DEBUG_OSPF_EVENT
)
356 zlog_debug("%s: route is not BB-associated",
358 return; /* We can update only BB routes */
362 if (or->cost
< cost
) {
363 if (IS_DEBUG_OSPF_EVENT
)
364 zlog_debug("%s: new route is worse", __func__
);
368 if (or->cost
== cost
) {
369 if (IS_DEBUG_OSPF_EVENT
)
371 "%s: new route is same distance, adding nexthops",
373 ospf_route_copy_nexthops(or, abr_or
->paths
);
376 if (or->cost
> cost
) {
377 if (IS_DEBUG_OSPF_EVENT
)
379 "%s: new route is better, overriding nexthops",
381 ospf_route_subst_nexthops(or, abr_or
->paths
);
384 if ((ospf
->abr_type
== OSPF_ABR_SHORTCUT
)
385 && !OSPF_IS_AREA_ID_BACKBONE(or->u
.std
.area_id
)) {
386 or->path_type
= OSPF_PATH_INTER_AREA
;
387 or->u
.std
.area_id
= area
->area_id
;
388 or->u
.std
.external_routing
= area
->external_routing
;
389 /* Note that we can do this only in Shortcut ABR mode,
390 because standard ABR must leave the route type and
398 static void ospf_update_router_route(struct ospf
*ospf
,
399 struct route_table
*rtrs
,
400 struct summary_lsa
*lsa
,
401 struct prefix_ipv4
*p
,
402 struct ospf_area
*area
)
404 struct ospf_route
* or, *abr_or
, *new_or
;
405 struct prefix_ipv4 abr
;
408 abr
.family
= AF_INET
;
409 abr
.prefix
= lsa
->header
.adv_router
;
410 abr
.prefixlen
= IPV4_MAX_BITLEN
;
411 apply_mask_ipv4(&abr
);
413 abr_or
= ospf_find_abr_route(rtrs
, &abr
, area
);
415 if (abr_or
== NULL
) {
416 if (IS_DEBUG_OSPF_EVENT
)
417 zlog_debug("%s: can't find a route to the ABR",
422 cost
= abr_or
->cost
+ GET_METRIC(lsa
->metric
);
424 /* First try to find a backbone path,
425 because standard ABR can update only BB-associated paths */
427 if ((ospf
->backbone
== NULL
) && (ospf
->abr_type
!= OSPF_ABR_SHORTCUT
))
428 return; /* no BB area, not Shortcut ABR, exiting */
430 /* find the backbone route, if possible */
431 if ((ospf
->backbone
== NULL
)
432 || !(or = ospf_find_asbr_route_through_area(rtrs
, p
,
434 if (ospf
->abr_type
!= OSPF_ABR_SHORTCUT
)
436 /* route to ASBR through the BB not found
437 the router is not Shortcut ABR, exiting */
441 /* We're a Shortcut ABR*/
443 /* Let it either add a new router or update the route
444 through the same (non-BB) area. */
446 new_or
= ospf_route_new();
447 new_or
->type
= OSPF_DESTINATION_ROUTER
;
448 new_or
->id
= lsa
->header
.id
;
449 new_or
->mask
= lsa
->mask
;
450 new_or
->u
.std
.options
= lsa
->header
.options
;
451 new_or
->u
.std
.origin
= (struct lsa_header
*)lsa
;
453 new_or
->u
.std
.area_id
= area
->area_id
;
454 new_or
->u
.std
.external_routing
= area
->external_routing
;
455 new_or
->path_type
= OSPF_PATH_INTER_AREA
;
456 new_or
->u
.std
.flags
= ROUTER_LSA_EXTERNAL
;
457 ospf_ia_router_route(ospf
, rtrs
, p
, new_or
, abr_or
);
463 /* At this point the "or" is always bb-associated */
465 if (!(or->u
.std
.flags
& ROUTER_LSA_EXTERNAL
)) {
466 if (IS_DEBUG_OSPF_EVENT
)
467 zlog_debug("%s: the remote router is not an ASBR",
472 if (or->path_type
!= OSPF_PATH_INTRA_AREA
&&
473 or->path_type
!= OSPF_PATH_INTER_AREA
)
479 else if (or->cost
== cost
)
480 ospf_route_copy_nexthops(or, abr_or
->paths
);
482 else if (or->cost
> cost
) {
483 ospf_route_subst_nexthops(or, abr_or
->paths
);
486 /* Even if the ABR runs in Shortcut mode, we can't change
487 the path type and area, because the "or" is always
489 at this point and even Shortcut ABR can't change these
494 static int process_transit_summary_lsa(struct ospf_area
*area
,
495 struct route_table
*rt
,
496 struct route_table
*rtrs
,
497 struct ospf_lsa
*lsa
)
499 struct ospf
*ospf
= area
->ospf
;
500 struct summary_lsa
*sl
;
501 struct prefix_ipv4 p
;
507 sl
= (struct summary_lsa
*)lsa
->data
;
509 if (IS_DEBUG_OSPF_EVENT
)
510 zlog_debug("%s: LS ID: %pI4", __func__
, &lsa
->data
->id
);
511 metric
= GET_METRIC(sl
->metric
);
513 if (metric
== OSPF_LS_INFINITY
) {
514 if (IS_DEBUG_OSPF_EVENT
)
515 zlog_debug("%s: metric is infinity, skip", __func__
);
519 if (IS_LSA_MAXAGE(lsa
)) {
520 if (IS_DEBUG_OSPF_EVENT
)
521 zlog_debug("%s: This LSA is too old", __func__
);
525 if (ospf_lsa_is_self_originated(area
->ospf
, lsa
)) {
526 if (IS_DEBUG_OSPF_EVENT
)
527 zlog_debug("%s: This LSA is mine, skip", __func__
);
532 p
.prefix
= sl
->header
.id
;
534 if (sl
->header
.type
== OSPF_SUMMARY_LSA
)
535 p
.prefixlen
= ip_masklen(sl
->mask
);
537 p
.prefixlen
= IPV4_MAX_BITLEN
;
541 if (sl
->header
.type
== OSPF_SUMMARY_LSA
)
542 ospf_update_network_route(ospf
, rt
, rtrs
, sl
, &p
, area
);
544 ospf_update_router_route(ospf
, rtrs
, sl
, &p
, area
);
549 static void ospf_examine_transit_summaries(struct ospf_area
*area
,
550 struct route_table
*lsdb_rt
,
551 struct route_table
*rt
,
552 struct route_table
*rtrs
)
554 struct ospf_lsa
*lsa
;
555 struct route_node
*rn
;
557 LSDB_LOOP (lsdb_rt
, rn
, lsa
)
558 process_transit_summary_lsa(area
, rt
, rtrs
, lsa
);
561 void ospf_ia_routing(struct ospf
*ospf
, struct route_table
*rt
,
562 struct route_table
*rtrs
)
564 struct listnode
*node
;
565 struct ospf_area
*area
;
567 if (IS_DEBUG_OSPF_EVENT
)
568 zlog_debug("%s:start", __func__
);
570 if (IS_OSPF_ABR(ospf
)) {
571 switch (ospf
->abr_type
) {
573 if (IS_DEBUG_OSPF_EVENT
)
574 zlog_debug("%s:Standard ABR", __func__
);
576 if ((area
= ospf
->backbone
)) {
577 if (IS_DEBUG_OSPF_EVENT
) {
579 "%s:backbone area found, examining summaries",
583 OSPF_EXAMINE_SUMMARIES_ALL(area
, rt
, rtrs
);
585 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, node
,
587 if (area
!= ospf
->backbone
)
588 if (ospf_area_is_transit(area
))
589 OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
591 } else if (IS_DEBUG_OSPF_EVENT
)
592 zlog_debug("%s:backbone area NOT found",
597 if (IS_DEBUG_OSPF_EVENT
)
598 zlog_debug("%s:Alternative Cisco/IBM ABR",
600 area
= ospf
->backbone
; /* Find the BB */
602 /* If we have an active BB connection */
603 if (area
&& ospf_act_bb_connection(ospf
)) {
604 if (IS_DEBUG_OSPF_EVENT
) {
606 "%s: backbone area found, examining BB summaries",
610 OSPF_EXAMINE_SUMMARIES_ALL(area
, rt
, rtrs
);
612 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, node
,
614 if (area
!= ospf
->backbone
)
615 if (ospf_area_is_transit(area
))
616 OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
618 } else { /* No active BB connection--consider all areas
620 if (IS_DEBUG_OSPF_EVENT
)
622 "%s: Active BB connection not found",
624 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, node
,
626 OSPF_EXAMINE_SUMMARIES_ALL(area
, rt
,
630 case OSPF_ABR_SHORTCUT
:
631 if (IS_DEBUG_OSPF_EVENT
)
632 zlog_debug("%s:Alternative Shortcut", __func__
);
633 area
= ospf
->backbone
; /* Find the BB */
635 /* If we have an active BB connection */
636 if (area
&& ospf_act_bb_connection(ospf
)) {
637 if (IS_DEBUG_OSPF_EVENT
) {
639 "%s: backbone area found, examining BB summaries",
642 OSPF_EXAMINE_SUMMARIES_ALL(area
, rt
, rtrs
);
645 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, node
, area
))
646 if (area
!= ospf
->backbone
)
647 if (ospf_area_is_transit(area
)
648 || ((area
->shortcut_configured
649 != OSPF_SHORTCUT_DISABLE
)
650 && ((ospf
->backbone
== NULL
)
651 || ((area
->shortcut_configured
652 == OSPF_SHORTCUT_ENABLE
)
653 && area
->shortcut_capability
))))
654 OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
661 if (IS_DEBUG_OSPF_EVENT
)
662 zlog_debug("%s:not ABR, considering all areas",
665 for (ALL_LIST_ELEMENTS_RO(ospf
->areas
, node
, area
))
666 OSPF_EXAMINE_SUMMARIES_ALL(area
, rt
, rtrs
);