]> git.proxmox.com Git - mirror_frr.git/blob - ospfd/ospf_ia.c
Merge pull request #12818 from imzyxwvu/fix/other-table-inactive
[mirror_frr.git] / ospfd / ospf_ia.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * OSPF inter-area routing.
4 * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
5 */
6
7
8 #include <zebra.h>
9
10 #include "thread.h"
11 #include "memory.h"
12 #include "hash.h"
13 #include "linklist.h"
14 #include "prefix.h"
15 #include "table.h"
16 #include "log.h"
17
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"
32
33 static struct ospf_route *ospf_find_abr_route(struct route_table *rtrs,
34 struct prefix_ipv4 *abr,
35 struct ospf_area *area)
36 {
37 struct route_node *rn;
38 struct ospf_route * or ;
39 struct listnode *node;
40
41 if ((rn = route_node_lookup(rtrs, (struct prefix *)abr)) == NULL)
42 return NULL;
43
44 route_unlock_node(rn);
45
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))
49 return or ;
50
51 return NULL;
52 }
53
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)
58 {
59 struct route_node *rn1;
60 struct ospf_route * or ;
61
62 if (IS_DEBUG_OSPF_EVENT)
63 zlog_debug("%s: processing summary route to %pFX", __func__, p);
64
65 /* Find a route to the same dest */
66 if ((rn1 = route_node_lookup(rt, (struct prefix *)p))) {
67 int res;
68
69 route_unlock_node(rn1);
70
71 if ((or = rn1->info)) {
72 if (IS_DEBUG_OSPF_EVENT)
73 zlog_debug(
74 "%s: Found a route to the same network",
75 __func__);
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
82 * be added. */
83 route_lock_node(rn1);
84 ospf_route_copy_nexthops(or, abr_or->paths);
85 route_unlock_node(rn1);
86
87 /* new route can be deleted, because existing
88 * route has been updated. */
89 ospf_route_free(new_or);
90 } else {
91 /* New route is worse, so free it. */
92 ospf_route_free(new_or);
93 return;
94 }
95 } /* if (or)*/
96 } /*if (rn1)*/
97 else { /* no route */
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);
101 }
102 }
103
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)
108 {
109 struct ospf_route * or = NULL;
110 struct route_node *rn;
111 int ret;
112
113 if (IS_DEBUG_OSPF_EVENT)
114 zlog_debug("%s: considering %pFX", __func__, p);
115
116 /* Find a route to the same dest */
117 rn = route_node_get(rtrs, (struct prefix *)p);
118
119 if (rn->info == NULL)
120 /* This is a new route */
121 rn->info = list_new();
122 else {
123 struct ospf_area *or_area;
124 or_area = ospf_area_lookup_by_area_id(ospf,
125 new_or->u.std.area_id);
126 assert(or_area);
127 /* This is an additional route */
128 route_unlock_node(rn);
129 or = ospf_find_asbr_route_through_area(rtrs, p, or_area);
130 }
131
132 if (or) {
133 if (IS_DEBUG_OSPF_EVENT)
134 zlog_debug(
135 "%s: a route to the same ABR through the same area exists",
136 __func__);
137 /* New route is better */
138 if ((ret = ospf_route_cmp(ospf, new_or, or)) < 0) {
139 listnode_delete(rn->info, or);
140 ospf_route_free(or);
141 /* proceed down */
142 }
143 /* Routes are the same */
144 else if (ret == 0) {
145 if (IS_DEBUG_OSPF_EVENT)
146 zlog_debug("%s: merging the new route",
147 __func__);
148
149 ospf_route_copy_nexthops(or, abr_or->paths);
150 ospf_route_free(new_or);
151 return;
152 }
153 /* New route is worse */
154 else {
155 if (IS_DEBUG_OSPF_EVENT)
156 zlog_debug("%s: skipping the new route",
157 __func__);
158 ospf_route_free(new_or);
159 return;
160 }
161 }
162
163 ospf_route_copy_nexthops(new_or, abr_or->paths);
164
165 if (IS_DEBUG_OSPF_EVENT)
166 zlog_debug("%s: adding the new route", __func__);
167
168 listnode_add(rn->info, new_or);
169 }
170
171
172 static int process_summary_lsa(struct ospf_area *area, struct route_table *rt,
173 struct route_table *rtrs, struct ospf_lsa *lsa)
174 {
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;
180 uint32_t metric;
181
182 if (lsa == NULL)
183 return 0;
184
185 sl = (struct summary_lsa *)lsa->data;
186
187 if (IS_DEBUG_OSPF_EVENT)
188 zlog_debug("%s: LS ID: %pI4", __func__, &sl->header.id);
189
190 metric = GET_METRIC(sl->metric);
191
192 if (metric == OSPF_LS_INFINITY)
193 return 0;
194
195 if (IS_LSA_MAXAGE(lsa))
196 return 0;
197
198 if (ospf_lsa_is_self_originated(area->ospf, lsa))
199 return 0;
200
201 p.family = AF_INET;
202 p.prefix = sl->header.id;
203
204 if (sl->header.type == OSPF_SUMMARY_LSA)
205 p.prefixlen = ip_masklen(sl->mask);
206 else
207 p.prefixlen = IPV4_MAX_BITLEN;
208
209 apply_mask_ipv4(&p);
210
211 if (sl->header.type == OSPF_SUMMARY_LSA
212 && (range = ospf_area_range_match_any(ospf, &p))
213 && ospf_area_range_active(range))
214 return 0;
215
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?
219 */
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 */
224
225 abr.family = AF_INET;
226 abr.prefix = sl->header.adv_router;
227 abr.prefixlen = IPV4_MAX_BITLEN;
228 apply_mask_ipv4(&abr);
229
230 abr_or = ospf_find_abr_route(rtrs, &abr, area);
231
232 if (abr_or == NULL)
233 return 0;
234
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;
245
246 if (sl->header.type == OSPF_SUMMARY_LSA)
247 ospf_ia_network_route(ospf, rt, &p, new_or, abr_or);
248 else {
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);
252 }
253
254 return 0;
255 }
256
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)
261 {
262 struct ospf_lsa *lsa;
263 struct route_node *rn;
264
265 LSDB_LOOP (lsdb_rt, rn, lsa)
266 process_summary_lsa(area, rt, rtrs, lsa);
267 }
268
269 int ospf_area_is_transit(struct ospf_area *area)
270 {
271 return (area->transit == OSPF_TRANSIT_TRUE)
272 || ospf_full_virtual_nbrs(
273 area); /* Cisco forgets to set the V-bit :( */
274 }
275
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)
281 {
282 struct route_node *rn;
283 struct ospf_route * or, *abr_or, *new_or;
284 struct prefix_ipv4 abr;
285 uint32_t cost;
286
287 abr.family = AF_INET;
288 abr.prefix = lsa->header.adv_router;
289 abr.prefixlen = IPV4_MAX_BITLEN;
290 apply_mask_ipv4(&abr);
291
292 abr_or = ospf_find_abr_route(rtrs, &abr, area);
293
294 if (abr_or == NULL) {
295 if (IS_DEBUG_OSPF_EVENT)
296 zlog_debug("%s: can't find a route to the ABR",
297 __func__);
298 return;
299 }
300
301 cost = abr_or->cost + GET_METRIC(lsa->metric);
302
303 rn = route_node_lookup(rt, (struct prefix *)p);
304
305 if (!rn) {
306 if (ospf->abr_type != OSPF_ABR_SHORTCUT)
307 return; /* Standard ABR can update only already
308 installed
309 backbone paths */
310 if (IS_DEBUG_OSPF_EVENT)
311 zlog_debug("%s: Allowing Shortcut ABR to add new route",
312 __func__);
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;
319 new_or->cost = cost;
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);
324
325 return;
326 } else {
327 route_unlock_node(rn);
328 if (rn->info == NULL)
329 return;
330 }
331
332 or = rn->info;
333
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__);
338 return;
339 }
340
341 if (ospf->abr_type == OSPF_ABR_SHORTCUT) {
342 if (
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)
347 zlog_debug(
348 "%s: Shortcut: this intra-area path is not backbone",
349 __func__);
350 return;
351 }
352 } else /* Not Shortcut ABR */
353 {
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",
357 __func__);
358 return; /* We can update only BB routes */
359 }
360 }
361
362 if (or->cost < cost) {
363 if (IS_DEBUG_OSPF_EVENT)
364 zlog_debug("%s: new route is worse", __func__);
365 return;
366 }
367
368 if (or->cost == cost) {
369 if (IS_DEBUG_OSPF_EVENT)
370 zlog_debug(
371 "%s: new route is same distance, adding nexthops",
372 __func__);
373 ospf_route_copy_nexthops(or, abr_or->paths);
374 }
375
376 if (or->cost > cost) {
377 if (IS_DEBUG_OSPF_EVENT)
378 zlog_debug(
379 "%s: new route is better, overriding nexthops",
380 __func__);
381 ospf_route_subst_nexthops(or, abr_or->paths);
382 or->cost = cost;
383
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
391 area
392 unchanged
393 */
394 }
395 }
396 }
397
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)
403 {
404 struct ospf_route * or, *abr_or, *new_or;
405 struct prefix_ipv4 abr;
406 uint32_t cost;
407
408 abr.family = AF_INET;
409 abr.prefix = lsa->header.adv_router;
410 abr.prefixlen = IPV4_MAX_BITLEN;
411 apply_mask_ipv4(&abr);
412
413 abr_or = ospf_find_abr_route(rtrs, &abr, area);
414
415 if (abr_or == NULL) {
416 if (IS_DEBUG_OSPF_EVENT)
417 zlog_debug("%s: can't find a route to the ABR",
418 __func__);
419 return;
420 }
421
422 cost = abr_or->cost + GET_METRIC(lsa->metric);
423
424 /* First try to find a backbone path,
425 because standard ABR can update only BB-associated paths */
426
427 if ((ospf->backbone == NULL) && (ospf->abr_type != OSPF_ABR_SHORTCUT))
428 return; /* no BB area, not Shortcut ABR, exiting */
429
430 /* find the backbone route, if possible */
431 if ((ospf->backbone == NULL)
432 || !(or = ospf_find_asbr_route_through_area(rtrs, p,
433 ospf->backbone))) {
434 if (ospf->abr_type != OSPF_ABR_SHORTCUT)
435
436 /* route to ASBR through the BB not found
437 the router is not Shortcut ABR, exiting */
438
439 return;
440 else
441 /* We're a Shortcut ABR*/
442 {
443 /* Let it either add a new router or update the route
444 through the same (non-BB) area. */
445
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;
452 new_or->cost = cost;
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);
458
459 return;
460 }
461 }
462
463 /* At this point the "or" is always bb-associated */
464
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",
468 __func__);
469 return;
470 }
471
472 if (or->path_type != OSPF_PATH_INTRA_AREA &&
473 or->path_type != OSPF_PATH_INTER_AREA)
474 return;
475
476 if (or->cost < cost)
477 return;
478
479 else if (or->cost == cost)
480 ospf_route_copy_nexthops(or, abr_or->paths);
481
482 else if (or->cost > cost) {
483 ospf_route_subst_nexthops(or, abr_or->paths);
484 or->cost = cost;
485
486 /* Even if the ABR runs in Shortcut mode, we can't change
487 the path type and area, because the "or" is always
488 bb-associated
489 at this point and even Shortcut ABR can't change these
490 attributes */
491 }
492 }
493
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)
498 {
499 struct ospf *ospf = area->ospf;
500 struct summary_lsa *sl;
501 struct prefix_ipv4 p;
502 uint32_t metric;
503
504 if (lsa == NULL)
505 return 0;
506
507 sl = (struct summary_lsa *)lsa->data;
508
509 if (IS_DEBUG_OSPF_EVENT)
510 zlog_debug("%s: LS ID: %pI4", __func__, &lsa->data->id);
511 metric = GET_METRIC(sl->metric);
512
513 if (metric == OSPF_LS_INFINITY) {
514 if (IS_DEBUG_OSPF_EVENT)
515 zlog_debug("%s: metric is infinity, skip", __func__);
516 return 0;
517 }
518
519 if (IS_LSA_MAXAGE(lsa)) {
520 if (IS_DEBUG_OSPF_EVENT)
521 zlog_debug("%s: This LSA is too old", __func__);
522 return 0;
523 }
524
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__);
528 return 0;
529 }
530
531 p.family = AF_INET;
532 p.prefix = sl->header.id;
533
534 if (sl->header.type == OSPF_SUMMARY_LSA)
535 p.prefixlen = ip_masklen(sl->mask);
536 else
537 p.prefixlen = IPV4_MAX_BITLEN;
538
539 apply_mask_ipv4(&p);
540
541 if (sl->header.type == OSPF_SUMMARY_LSA)
542 ospf_update_network_route(ospf, rt, rtrs, sl, &p, area);
543 else
544 ospf_update_router_route(ospf, rtrs, sl, &p, area);
545
546 return 0;
547 }
548
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)
553 {
554 struct ospf_lsa *lsa;
555 struct route_node *rn;
556
557 LSDB_LOOP (lsdb_rt, rn, lsa)
558 process_transit_summary_lsa(area, rt, rtrs, lsa);
559 }
560
561 void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
562 struct route_table *rtrs)
563 {
564 struct listnode *node;
565 struct ospf_area *area;
566
567 if (IS_DEBUG_OSPF_EVENT)
568 zlog_debug("%s:start", __func__);
569
570 if (IS_OSPF_ABR(ospf)) {
571 switch (ospf->abr_type) {
572 case OSPF_ABR_STAND:
573 if (IS_DEBUG_OSPF_EVENT)
574 zlog_debug("%s:Standard ABR", __func__);
575
576 if ((area = ospf->backbone)) {
577 if (IS_DEBUG_OSPF_EVENT) {
578 zlog_debug(
579 "%s:backbone area found, examining summaries",
580 __func__);
581 }
582
583 OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
584
585 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
586 area))
587 if (area != ospf->backbone)
588 if (ospf_area_is_transit(area))
589 OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
590 area, rt, rtrs);
591 } else if (IS_DEBUG_OSPF_EVENT)
592 zlog_debug("%s:backbone area NOT found",
593 __func__);
594 break;
595 case OSPF_ABR_IBM:
596 case OSPF_ABR_CISCO:
597 if (IS_DEBUG_OSPF_EVENT)
598 zlog_debug("%s:Alternative Cisco/IBM ABR",
599 __func__);
600 area = ospf->backbone; /* Find the BB */
601
602 /* If we have an active BB connection */
603 if (area && ospf_act_bb_connection(ospf)) {
604 if (IS_DEBUG_OSPF_EVENT) {
605 zlog_debug(
606 "%s: backbone area found, examining BB summaries",
607 __func__);
608 }
609
610 OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
611
612 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
613 area))
614 if (area != ospf->backbone)
615 if (ospf_area_is_transit(area))
616 OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
617 area, rt, rtrs);
618 } else { /* No active BB connection--consider all areas
619 */
620 if (IS_DEBUG_OSPF_EVENT)
621 zlog_debug(
622 "%s: Active BB connection not found",
623 __func__);
624 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
625 area))
626 OSPF_EXAMINE_SUMMARIES_ALL(area, rt,
627 rtrs);
628 }
629 break;
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 */
634
635 /* If we have an active BB connection */
636 if (area && ospf_act_bb_connection(ospf)) {
637 if (IS_DEBUG_OSPF_EVENT) {
638 zlog_debug(
639 "%s: backbone area found, examining BB summaries",
640 __func__);
641 }
642 OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
643 }
644
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(
655 area, rt, rtrs);
656 break;
657 default:
658 break;
659 }
660 } else {
661 if (IS_DEBUG_OSPF_EVENT)
662 zlog_debug("%s:not ABR, considering all areas",
663 __func__);
664
665 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
666 OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
667 }
668 }