Line data Source code
1 : /*
2 : * OSPF inter-area routing.
3 : * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada
4 : *
5 : * This file is part of GNU Zebra.
6 : *
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
10 : * later version.
11 : *
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.
16 : *
17 : * You should have received a copy of the GNU General Public License along
18 : * with this program; see the file COPYING; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 : */
21 :
22 :
23 : #include <zebra.h>
24 :
25 : #include "thread.h"
26 : #include "memory.h"
27 : #include "hash.h"
28 : #include "linklist.h"
29 : #include "prefix.h"
30 : #include "table.h"
31 : #include "log.h"
32 :
33 : #include "ospfd/ospfd.h"
34 : #include "ospfd/ospf_interface.h"
35 : #include "ospfd/ospf_ism.h"
36 : #include "ospfd/ospf_asbr.h"
37 : #include "ospfd/ospf_lsa.h"
38 : #include "ospfd/ospf_lsdb.h"
39 : #include "ospfd/ospf_neighbor.h"
40 : #include "ospfd/ospf_nsm.h"
41 : #include "ospfd/ospf_spf.h"
42 : #include "ospfd/ospf_route.h"
43 : #include "ospfd/ospf_ase.h"
44 : #include "ospfd/ospf_abr.h"
45 : #include "ospfd/ospf_ia.h"
46 : #include "ospfd/ospf_dump.h"
47 :
48 47 : static struct ospf_route *ospf_find_abr_route(struct route_table *rtrs,
49 : struct prefix_ipv4 *abr,
50 : struct ospf_area *area)
51 : {
52 47 : struct route_node *rn;
53 47 : struct ospf_route * or ;
54 47 : struct listnode *node;
55 :
56 47 : if ((rn = route_node_lookup(rtrs, (struct prefix *)abr)) == NULL)
57 : return NULL;
58 :
59 18 : route_unlock_node(rn);
60 :
61 36 : for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or))
62 18 : if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)
63 18 : && (or->u.std.flags & ROUTER_LSA_BORDER))
64 18 : return or ;
65 :
66 : return NULL;
67 : }
68 :
69 13 : static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt,
70 : struct prefix_ipv4 *p,
71 : struct ospf_route *new_or,
72 : struct ospf_route *abr_or)
73 : {
74 13 : struct route_node *rn1;
75 13 : struct ospf_route * or ;
76 :
77 13 : if (IS_DEBUG_OSPF_EVENT)
78 13 : zlog_debug("%s: processing summary route to %pFX", __func__, p);
79 :
80 : /* Find a route to the same dest */
81 13 : if ((rn1 = route_node_lookup(rt, (struct prefix *)p))) {
82 0 : int res;
83 :
84 0 : route_unlock_node(rn1);
85 :
86 0 : if ((or = rn1->info)) {
87 0 : if (IS_DEBUG_OSPF_EVENT)
88 0 : zlog_debug(
89 : "%s: Found a route to the same network",
90 : __func__);
91 : /* Check the existing route. */
92 0 : if ((res = ospf_route_cmp(ospf, new_or, or)) < 0) {
93 : /* New route is better, so replace old one. */
94 0 : ospf_route_subst(rn1, new_or, abr_or);
95 0 : } else if (res == 0) {
96 : /* New and old route are equal, so next hops can
97 : * be added. */
98 0 : route_lock_node(rn1);
99 0 : ospf_route_copy_nexthops(or, abr_or->paths);
100 0 : route_unlock_node(rn1);
101 :
102 : /* new route can be deleted, because existing
103 : * route has been updated. */
104 0 : ospf_route_free(new_or);
105 : } else {
106 : /* New route is worse, so free it. */
107 0 : ospf_route_free(new_or);
108 0 : return;
109 : }
110 : } /* if (or)*/
111 : } /*if (rn1)*/
112 : else { /* no route */
113 13 : if (IS_DEBUG_OSPF_EVENT)
114 13 : zlog_debug("%s: add new route to %pFX", __func__, p);
115 13 : ospf_route_add(rt, p, new_or, abr_or);
116 : }
117 : }
118 :
119 5 : static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
120 : struct prefix_ipv4 *p,
121 : struct ospf_route *new_or,
122 : struct ospf_route *abr_or)
123 : {
124 5 : struct ospf_route * or = NULL;
125 5 : struct route_node *rn;
126 5 : int ret;
127 :
128 5 : if (IS_DEBUG_OSPF_EVENT)
129 5 : zlog_debug("%s: considering %pFX", __func__, p);
130 :
131 : /* Find a route to the same dest */
132 5 : rn = route_node_get(rtrs, (struct prefix *)p);
133 :
134 5 : if (rn->info == NULL)
135 : /* This is a new route */
136 5 : rn->info = list_new();
137 : else {
138 0 : struct ospf_area *or_area;
139 0 : or_area = ospf_area_lookup_by_area_id(ospf,
140 : new_or->u.std.area_id);
141 0 : assert(or_area);
142 : /* This is an additional route */
143 0 : route_unlock_node(rn);
144 0 : or = ospf_find_asbr_route_through_area(rtrs, p, or_area);
145 : }
146 :
147 5 : if (or) {
148 0 : if (IS_DEBUG_OSPF_EVENT)
149 0 : zlog_debug(
150 : "%s: a route to the same ABR through the same area exists",
151 : __func__);
152 : /* New route is better */
153 0 : if ((ret = ospf_route_cmp(ospf, new_or, or)) < 0) {
154 0 : listnode_delete(rn->info, or);
155 0 : ospf_route_free(or);
156 : /* proceed down */
157 : }
158 : /* Routes are the same */
159 0 : else if (ret == 0) {
160 0 : if (IS_DEBUG_OSPF_EVENT)
161 0 : zlog_debug("%s: merging the new route",
162 : __func__);
163 :
164 0 : ospf_route_copy_nexthops(or, abr_or->paths);
165 0 : ospf_route_free(new_or);
166 0 : return;
167 : }
168 : /* New route is worse */
169 : else {
170 0 : if (IS_DEBUG_OSPF_EVENT)
171 0 : zlog_debug("%s: skipping the new route",
172 : __func__);
173 0 : ospf_route_free(new_or);
174 0 : return;
175 : }
176 : }
177 :
178 5 : ospf_route_copy_nexthops(new_or, abr_or->paths);
179 :
180 5 : if (IS_DEBUG_OSPF_EVENT)
181 5 : zlog_debug("%s: adding the new route", __func__);
182 :
183 5 : listnode_add(rn->info, new_or);
184 : }
185 :
186 :
187 86 : static int process_summary_lsa(struct ospf_area *area, struct route_table *rt,
188 : struct route_table *rtrs, struct ospf_lsa *lsa)
189 : {
190 86 : struct ospf *ospf = area->ospf;
191 86 : struct ospf_area_range *range;
192 86 : struct ospf_route *abr_or, *new_or;
193 86 : struct summary_lsa *sl;
194 86 : struct prefix_ipv4 p, abr;
195 86 : uint32_t metric;
196 :
197 86 : if (lsa == NULL)
198 : return 0;
199 :
200 86 : sl = (struct summary_lsa *)lsa->data;
201 :
202 86 : if (IS_DEBUG_OSPF_EVENT)
203 86 : zlog_debug("%s: LS ID: %pI4", __func__, &sl->header.id);
204 :
205 86 : metric = GET_METRIC(sl->metric);
206 :
207 86 : if (metric == OSPF_LS_INFINITY)
208 : return 0;
209 :
210 86 : if (IS_LSA_MAXAGE(lsa))
211 13 : return 0;
212 :
213 73 : if (ospf_lsa_is_self_originated(area->ospf, lsa))
214 : return 0;
215 :
216 47 : p.family = AF_INET;
217 47 : p.prefix = sl->header.id;
218 :
219 47 : if (sl->header.type == OSPF_SUMMARY_LSA)
220 34 : p.prefixlen = ip_masklen(sl->mask);
221 : else
222 13 : p.prefixlen = IPV4_MAX_BITLEN;
223 :
224 47 : apply_mask_ipv4(&p);
225 :
226 47 : if (sl->header.type == OSPF_SUMMARY_LSA
227 34 : && (range = ospf_area_range_match_any(ospf, &p))
228 0 : && ospf_area_range_active(range))
229 : return 0;
230 :
231 : /* XXX: This check seems dubious to me. If an ABR has already decided
232 : * to consider summaries received in this area, then why would one wish
233 : * to exclude default?
234 : */
235 47 : if (IS_OSPF_ABR(ospf) && ospf->abr_type != OSPF_ABR_STAND
236 0 : && area->external_routing != OSPF_AREA_DEFAULT
237 0 : && p.prefix.s_addr == OSPF_DEFAULT_DESTINATION && p.prefixlen == 0)
238 : return 0; /* Ignore summary default from a stub area */
239 :
240 47 : abr.family = AF_INET;
241 47 : abr.prefix = sl->header.adv_router;
242 47 : abr.prefixlen = IPV4_MAX_BITLEN;
243 47 : apply_mask_ipv4(&abr);
244 :
245 47 : abr_or = ospf_find_abr_route(rtrs, &abr, area);
246 :
247 47 : if (abr_or == NULL)
248 : return 0;
249 :
250 18 : new_or = ospf_route_new();
251 18 : new_or->type = OSPF_DESTINATION_NETWORK;
252 18 : new_or->id = sl->header.id;
253 18 : new_or->mask = sl->mask;
254 18 : new_or->u.std.options = sl->header.options;
255 18 : new_or->u.std.origin = (struct lsa_header *)sl;
256 18 : new_or->cost = abr_or->cost + metric;
257 18 : new_or->u.std.area_id = area->area_id;
258 18 : new_or->u.std.external_routing = area->external_routing;
259 18 : new_or->path_type = OSPF_PATH_INTER_AREA;
260 :
261 18 : if (sl->header.type == OSPF_SUMMARY_LSA)
262 13 : ospf_ia_network_route(ospf, rt, &p, new_or, abr_or);
263 : else {
264 5 : new_or->type = OSPF_DESTINATION_ROUTER;
265 5 : new_or->u.std.flags = ROUTER_LSA_EXTERNAL;
266 5 : ospf_ia_router_route(ospf, rtrs, &p, new_or, abr_or);
267 : }
268 :
269 : return 0;
270 : }
271 :
272 104 : static void ospf_examine_summaries(struct ospf_area *area,
273 : struct route_table *lsdb_rt,
274 : struct route_table *rt,
275 : struct route_table *rtrs)
276 : {
277 104 : struct ospf_lsa *lsa;
278 104 : struct route_node *rn;
279 :
280 226 : LSDB_LOOP (lsdb_rt, rn, lsa)
281 86 : process_summary_lsa(area, rt, rtrs, lsa);
282 104 : }
283 :
284 3 : int ospf_area_is_transit(struct ospf_area *area)
285 : {
286 3 : return (area->transit == OSPF_TRANSIT_TRUE)
287 3 : || ospf_full_virtual_nbrs(
288 : area); /* Cisco forgets to set the V-bit :( */
289 : }
290 :
291 0 : static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt,
292 : struct route_table *rtrs,
293 : struct summary_lsa *lsa,
294 : struct prefix_ipv4 *p,
295 : struct ospf_area *area)
296 : {
297 0 : struct route_node *rn;
298 0 : struct ospf_route * or, *abr_or, *new_or;
299 0 : struct prefix_ipv4 abr;
300 0 : uint32_t cost;
301 :
302 0 : abr.family = AF_INET;
303 0 : abr.prefix = lsa->header.adv_router;
304 0 : abr.prefixlen = IPV4_MAX_BITLEN;
305 0 : apply_mask_ipv4(&abr);
306 :
307 0 : abr_or = ospf_find_abr_route(rtrs, &abr, area);
308 :
309 0 : if (abr_or == NULL) {
310 0 : if (IS_DEBUG_OSPF_EVENT)
311 0 : zlog_debug("%s: can't find a route to the ABR",
312 : __func__);
313 0 : return;
314 : }
315 :
316 0 : cost = abr_or->cost + GET_METRIC(lsa->metric);
317 :
318 0 : rn = route_node_lookup(rt, (struct prefix *)p);
319 :
320 0 : if (!rn) {
321 0 : if (ospf->abr_type != OSPF_ABR_SHORTCUT)
322 : return; /* Standard ABR can update only already
323 : installed
324 : backbone paths */
325 0 : if (IS_DEBUG_OSPF_EVENT)
326 0 : zlog_debug("%s: Allowing Shortcut ABR to add new route",
327 : __func__);
328 0 : new_or = ospf_route_new();
329 0 : new_or->type = OSPF_DESTINATION_NETWORK;
330 0 : new_or->id = lsa->header.id;
331 0 : new_or->mask = lsa->mask;
332 0 : new_or->u.std.options = lsa->header.options;
333 0 : new_or->u.std.origin = (struct lsa_header *)lsa;
334 0 : new_or->cost = cost;
335 0 : new_or->u.std.area_id = area->area_id;
336 0 : new_or->u.std.external_routing = area->external_routing;
337 0 : new_or->path_type = OSPF_PATH_INTER_AREA;
338 0 : ospf_route_add(rt, p, new_or, abr_or);
339 :
340 0 : return;
341 : } else {
342 0 : route_unlock_node(rn);
343 0 : if (rn->info == NULL)
344 : return;
345 : }
346 :
347 0 : or = rn->info;
348 :
349 0 : if (or->path_type != OSPF_PATH_INTRA_AREA &&
350 : or->path_type != OSPF_PATH_INTER_AREA) {
351 0 : if (IS_DEBUG_OSPF_EVENT)
352 0 : zlog_debug("%s: ERR: path type is wrong", __func__);
353 0 : return;
354 : }
355 :
356 0 : if (ospf->abr_type == OSPF_ABR_SHORTCUT) {
357 0 : if (
358 : or->path_type == OSPF_PATH_INTRA_AREA
359 0 : && !OSPF_IS_AREA_ID_BACKBONE(
360 : or->u.std.area_id)) {
361 0 : if (IS_DEBUG_OSPF_EVENT)
362 0 : zlog_debug(
363 : "%s: Shortcut: this intra-area path is not backbone",
364 : __func__);
365 0 : return;
366 : }
367 : } else /* Not Shortcut ABR */
368 : {
369 0 : if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) {
370 0 : if (IS_DEBUG_OSPF_EVENT)
371 0 : zlog_debug("%s: route is not BB-associated",
372 : __func__);
373 0 : return; /* We can update only BB routes */
374 : }
375 : }
376 :
377 0 : if (or->cost < cost) {
378 0 : if (IS_DEBUG_OSPF_EVENT)
379 0 : zlog_debug("%s: new route is worse", __func__);
380 0 : return;
381 : }
382 :
383 0 : if (or->cost == cost) {
384 0 : if (IS_DEBUG_OSPF_EVENT)
385 0 : zlog_debug(
386 : "%s: new route is same distance, adding nexthops",
387 : __func__);
388 0 : ospf_route_copy_nexthops(or, abr_or->paths);
389 : }
390 :
391 0 : if (or->cost > cost) {
392 0 : if (IS_DEBUG_OSPF_EVENT)
393 0 : zlog_debug(
394 : "%s: new route is better, overriding nexthops",
395 : __func__);
396 0 : ospf_route_subst_nexthops(or, abr_or->paths);
397 0 : or->cost = cost;
398 :
399 0 : if ((ospf->abr_type == OSPF_ABR_SHORTCUT)
400 0 : && !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) {
401 0 : or->path_type = OSPF_PATH_INTER_AREA;
402 0 : or->u.std.area_id = area->area_id;
403 0 : or->u.std.external_routing = area->external_routing;
404 : /* Note that we can do this only in Shortcut ABR mode,
405 : because standard ABR must leave the route type and
406 : area
407 : unchanged
408 : */
409 : }
410 : }
411 : }
412 :
413 0 : static void ospf_update_router_route(struct ospf *ospf,
414 : struct route_table *rtrs,
415 : struct summary_lsa *lsa,
416 : struct prefix_ipv4 *p,
417 : struct ospf_area *area)
418 : {
419 0 : struct ospf_route * or, *abr_or, *new_or;
420 0 : struct prefix_ipv4 abr;
421 0 : uint32_t cost;
422 :
423 0 : abr.family = AF_INET;
424 0 : abr.prefix = lsa->header.adv_router;
425 0 : abr.prefixlen = IPV4_MAX_BITLEN;
426 0 : apply_mask_ipv4(&abr);
427 :
428 0 : abr_or = ospf_find_abr_route(rtrs, &abr, area);
429 :
430 0 : if (abr_or == NULL) {
431 0 : if (IS_DEBUG_OSPF_EVENT)
432 0 : zlog_debug("%s: can't find a route to the ABR",
433 : __func__);
434 0 : return;
435 : }
436 :
437 0 : cost = abr_or->cost + GET_METRIC(lsa->metric);
438 :
439 : /* First try to find a backbone path,
440 : because standard ABR can update only BB-associated paths */
441 :
442 0 : if ((ospf->backbone == NULL) && (ospf->abr_type != OSPF_ABR_SHORTCUT))
443 : return; /* no BB area, not Shortcut ABR, exiting */
444 :
445 : /* find the backbone route, if possible */
446 0 : if ((ospf->backbone == NULL)
447 0 : || !(or = ospf_find_asbr_route_through_area(rtrs, p,
448 : ospf->backbone))) {
449 0 : if (ospf->abr_type != OSPF_ABR_SHORTCUT)
450 :
451 : /* route to ASBR through the BB not found
452 : the router is not Shortcut ABR, exiting */
453 :
454 : return;
455 : else
456 : /* We're a Shortcut ABR*/
457 : {
458 : /* Let it either add a new router or update the route
459 : through the same (non-BB) area. */
460 :
461 0 : new_or = ospf_route_new();
462 0 : new_or->type = OSPF_DESTINATION_ROUTER;
463 0 : new_or->id = lsa->header.id;
464 0 : new_or->mask = lsa->mask;
465 0 : new_or->u.std.options = lsa->header.options;
466 0 : new_or->u.std.origin = (struct lsa_header *)lsa;
467 0 : new_or->cost = cost;
468 0 : new_or->u.std.area_id = area->area_id;
469 0 : new_or->u.std.external_routing = area->external_routing;
470 0 : new_or->path_type = OSPF_PATH_INTER_AREA;
471 0 : new_or->u.std.flags = ROUTER_LSA_EXTERNAL;
472 0 : ospf_ia_router_route(ospf, rtrs, p, new_or, abr_or);
473 :
474 0 : return;
475 : }
476 : }
477 :
478 : /* At this point the "or" is always bb-associated */
479 :
480 0 : if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL)) {
481 0 : if (IS_DEBUG_OSPF_EVENT)
482 0 : zlog_debug("%s: the remote router is not an ASBR",
483 : __func__);
484 0 : return;
485 : }
486 :
487 0 : if (or->path_type != OSPF_PATH_INTRA_AREA &&
488 : or->path_type != OSPF_PATH_INTER_AREA)
489 : return;
490 :
491 0 : if (or->cost < cost)
492 : return;
493 :
494 0 : else if (or->cost == cost)
495 0 : ospf_route_copy_nexthops(or, abr_or->paths);
496 :
497 0 : else if (or->cost > cost) {
498 0 : ospf_route_subst_nexthops(or, abr_or->paths);
499 0 : or->cost = cost;
500 :
501 : /* Even if the ABR runs in Shortcut mode, we can't change
502 : the path type and area, because the "or" is always
503 : bb-associated
504 : at this point and even Shortcut ABR can't change these
505 : attributes */
506 : }
507 : }
508 :
509 0 : static int process_transit_summary_lsa(struct ospf_area *area,
510 : struct route_table *rt,
511 : struct route_table *rtrs,
512 : struct ospf_lsa *lsa)
513 : {
514 0 : struct ospf *ospf = area->ospf;
515 0 : struct summary_lsa *sl;
516 0 : struct prefix_ipv4 p;
517 0 : uint32_t metric;
518 :
519 0 : if (lsa == NULL)
520 : return 0;
521 :
522 0 : sl = (struct summary_lsa *)lsa->data;
523 :
524 0 : if (IS_DEBUG_OSPF_EVENT)
525 0 : zlog_debug("%s: LS ID: %pI4", __func__, &lsa->data->id);
526 0 : metric = GET_METRIC(sl->metric);
527 :
528 0 : if (metric == OSPF_LS_INFINITY) {
529 0 : if (IS_DEBUG_OSPF_EVENT)
530 0 : zlog_debug("%s: metric is infinity, skip", __func__);
531 0 : return 0;
532 : }
533 :
534 0 : if (IS_LSA_MAXAGE(lsa)) {
535 0 : if (IS_DEBUG_OSPF_EVENT)
536 0 : zlog_debug("%s: This LSA is too old", __func__);
537 0 : return 0;
538 : }
539 :
540 0 : if (ospf_lsa_is_self_originated(area->ospf, lsa)) {
541 0 : if (IS_DEBUG_OSPF_EVENT)
542 0 : zlog_debug("%s: This LSA is mine, skip", __func__);
543 0 : return 0;
544 : }
545 :
546 0 : p.family = AF_INET;
547 0 : p.prefix = sl->header.id;
548 :
549 0 : if (sl->header.type == OSPF_SUMMARY_LSA)
550 0 : p.prefixlen = ip_masklen(sl->mask);
551 : else
552 0 : p.prefixlen = IPV4_MAX_BITLEN;
553 :
554 0 : apply_mask_ipv4(&p);
555 :
556 0 : if (sl->header.type == OSPF_SUMMARY_LSA)
557 0 : ospf_update_network_route(ospf, rt, rtrs, sl, &p, area);
558 : else
559 0 : ospf_update_router_route(ospf, rtrs, sl, &p, area);
560 :
561 : return 0;
562 : }
563 :
564 0 : static void ospf_examine_transit_summaries(struct ospf_area *area,
565 : struct route_table *lsdb_rt,
566 : struct route_table *rt,
567 : struct route_table *rtrs)
568 : {
569 0 : struct ospf_lsa *lsa;
570 0 : struct route_node *rn;
571 :
572 0 : LSDB_LOOP (lsdb_rt, rn, lsa)
573 0 : process_transit_summary_lsa(area, rt, rtrs, lsa);
574 0 : }
575 :
576 49 : void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
577 : struct route_table *rtrs)
578 : {
579 49 : struct listnode *node;
580 49 : struct ospf_area *area;
581 :
582 49 : if (IS_DEBUG_OSPF_EVENT)
583 49 : zlog_debug("%s:start", __func__);
584 :
585 49 : if (IS_OSPF_ABR(ospf)) {
586 9 : switch (ospf->abr_type) {
587 0 : case OSPF_ABR_STAND:
588 0 : if (IS_DEBUG_OSPF_EVENT)
589 0 : zlog_debug("%s:Standard ABR", __func__);
590 :
591 0 : if ((area = ospf->backbone)) {
592 0 : if (IS_DEBUG_OSPF_EVENT) {
593 0 : zlog_debug(
594 : "%s:backbone area found, examining summaries",
595 : __func__);
596 : }
597 :
598 0 : OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
599 :
600 0 : for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
601 : area))
602 0 : if (area != ospf->backbone)
603 0 : if (ospf_area_is_transit(area))
604 0 : OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
605 : area, rt, rtrs);
606 0 : } else if (IS_DEBUG_OSPF_EVENT)
607 0 : zlog_debug("%s:backbone area NOT found",
608 : __func__);
609 : break;
610 9 : case OSPF_ABR_IBM:
611 : case OSPF_ABR_CISCO:
612 9 : if (IS_DEBUG_OSPF_EVENT)
613 9 : zlog_debug("%s:Alternative Cisco/IBM ABR",
614 : __func__);
615 9 : area = ospf->backbone; /* Find the BB */
616 :
617 : /* If we have an active BB connection */
618 9 : if (area && ospf_act_bb_connection(ospf)) {
619 3 : if (IS_DEBUG_OSPF_EVENT) {
620 3 : zlog_debug(
621 : "%s: backbone area found, examining BB summaries",
622 : __func__);
623 : }
624 :
625 3 : OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
626 :
627 12 : for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
628 : area))
629 6 : if (area != ospf->backbone)
630 3 : if (ospf_area_is_transit(area))
631 0 : OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
632 : area, rt, rtrs);
633 : } else { /* No active BB connection--consider all areas
634 : */
635 6 : if (IS_DEBUG_OSPF_EVENT)
636 6 : zlog_debug(
637 : "%s: Active BB connection not found",
638 : __func__);
639 24 : for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
640 : area))
641 12 : OSPF_EXAMINE_SUMMARIES_ALL(area, rt,
642 : rtrs);
643 : }
644 : break;
645 0 : case OSPF_ABR_SHORTCUT:
646 0 : if (IS_DEBUG_OSPF_EVENT)
647 0 : zlog_debug("%s:Alternative Shortcut", __func__);
648 0 : area = ospf->backbone; /* Find the BB */
649 :
650 : /* If we have an active BB connection */
651 0 : if (area && ospf_act_bb_connection(ospf)) {
652 0 : if (IS_DEBUG_OSPF_EVENT) {
653 0 : zlog_debug(
654 : "%s: backbone area found, examining BB summaries",
655 : __func__);
656 : }
657 0 : OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
658 : }
659 :
660 0 : for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
661 0 : if (area != ospf->backbone)
662 0 : if (ospf_area_is_transit(area)
663 0 : || ((area->shortcut_configured
664 : != OSPF_SHORTCUT_DISABLE)
665 0 : && ((ospf->backbone == NULL)
666 0 : || ((area->shortcut_configured
667 : == OSPF_SHORTCUT_ENABLE)
668 0 : && area->shortcut_capability))))
669 0 : OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
670 : area, rt, rtrs);
671 : break;
672 : default:
673 : break;
674 : }
675 : } else {
676 40 : if (IS_DEBUG_OSPF_EVENT)
677 40 : zlog_debug("%s:not ABR, considering all areas",
678 : __func__);
679 :
680 117 : for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
681 37 : OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
682 : }
683 49 : }
|