]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
718e3744 | 2 | /* |
3 | * OSPF inter-area routing. | |
4 | * Copyright (C) 1999, 2000 Alex Zinin, Toshiaki Takada | |
718e3744 | 5 | */ |
6 | ||
7 | ||
8 | #include <zebra.h> | |
9 | ||
24a58196 | 10 | #include "frrevent.h" |
718e3744 | 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 | ||
d62a17ae | 33 | static struct ospf_route *ospf_find_abr_route(struct route_table *rtrs, |
34 | struct prefix_ipv4 *abr, | |
35 | struct ospf_area *area) | |
718e3744 | 36 | { |
d62a17ae | 37 | struct route_node *rn; |
38 | struct ospf_route * or ; | |
39 | struct listnode *node; | |
718e3744 | 40 | |
d62a17ae | 41 | if ((rn = route_node_lookup(rtrs, (struct prefix *)abr)) == NULL) |
42 | return NULL; | |
718e3744 | 43 | |
d62a17ae | 44 | route_unlock_node(rn); |
718e3744 | 45 | |
d62a17ae | 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 ; | |
718e3744 | 50 | |
d62a17ae | 51 | return NULL; |
718e3744 | 52 | } |
53 | ||
d62a17ae | 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) | |
718e3744 | 58 | { |
d62a17ae | 59 | struct route_node *rn1; |
60 | struct ospf_route * or ; | |
61 | ||
62 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 63 | zlog_debug("%s: processing summary route to %pFX", __func__, p); |
d62a17ae | 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( | |
0faaabfb | 74 | "%s: Found a route to the same network", |
75 | __func__); | |
d62a17ae | 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) | |
0faaabfb | 99 | zlog_debug("%s: add new route to %pFX", __func__, p); |
d62a17ae | 100 | ospf_route_add(rt, p, new_or, abr_or); |
101 | } | |
718e3744 | 102 | } |
103 | ||
d62a17ae | 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) | |
718e3744 | 108 | { |
d62a17ae | 109 | struct ospf_route * or = NULL; |
110 | struct route_node *rn; | |
111 | int ret; | |
112 | ||
113 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 114 | zlog_debug("%s: considering %pFX", __func__, p); |
96b663a3 | 115 | |
d62a17ae | 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); | |
718e3744 | 130 | } |
718e3744 | 131 | |
d62a17ae | 132 | if (or) { |
133 | if (IS_DEBUG_OSPF_EVENT) | |
134 | zlog_debug( | |
0faaabfb | 135 | "%s: a route to the same ABR through the same area exists", |
136 | __func__); | |
d62a17ae | 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) | |
0faaabfb | 146 | zlog_debug("%s: merging the new route", |
147 | __func__); | |
d62a17ae | 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) | |
0faaabfb | 156 | zlog_debug("%s: skipping the new route", |
157 | __func__); | |
d62a17ae | 158 | ospf_route_free(new_or); |
159 | return; | |
160 | } | |
718e3744 | 161 | } |
718e3744 | 162 | |
d62a17ae | 163 | ospf_route_copy_nexthops(new_or, abr_or->paths); |
718e3744 | 164 | |
d62a17ae | 165 | if (IS_DEBUG_OSPF_EVENT) |
0faaabfb | 166 | zlog_debug("%s: adding the new route", __func__); |
718e3744 | 167 | |
d62a17ae | 168 | listnode_add(rn->info, new_or); |
718e3744 | 169 | } |
170 | ||
6b0655a2 | 171 | |
d62a17ae | 172 | static int process_summary_lsa(struct ospf_area *area, struct route_table *rt, |
173 | struct route_table *rtrs, struct ospf_lsa *lsa) | |
718e3744 | 174 | { |
d62a17ae | 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; | |
d7c0a89a | 180 | uint32_t metric; |
d62a17ae | 181 | |
182 | if (lsa == NULL) | |
183 | return 0; | |
184 | ||
185 | sl = (struct summary_lsa *)lsa->data; | |
186 | ||
187 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 188 | zlog_debug("%s: LS ID: %pI4", __func__, &sl->header.id); |
d62a17ae | 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; | |
718e3744 | 255 | } |
256 | ||
d62a17ae | 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) | |
718e3744 | 261 | { |
d62a17ae | 262 | struct ospf_lsa *lsa; |
263 | struct route_node *rn; | |
96735eea | 264 | |
996c9314 | 265 | LSDB_LOOP (lsdb_rt, rn, lsa) |
044506e7 | 266 | process_summary_lsa(area, rt, rtrs, lsa); |
718e3744 | 267 | } |
268 | ||
d62a17ae | 269 | int ospf_area_is_transit(struct ospf_area *area) |
718e3744 | 270 | { |
d62a17ae | 271 | return (area->transit == OSPF_TRANSIT_TRUE) |
272 | || ospf_full_virtual_nbrs( | |
273 | area); /* Cisco forgets to set the V-bit :( */ | |
718e3744 | 274 | } |
275 | ||
d62a17ae | 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) | |
718e3744 | 281 | { |
d62a17ae | 282 | struct route_node *rn; |
283 | struct ospf_route * or, *abr_or, *new_or; | |
284 | struct prefix_ipv4 abr; | |
d7c0a89a | 285 | uint32_t cost; |
d62a17ae | 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) | |
0faaabfb | 296 | zlog_debug("%s: can't find a route to the ABR", |
297 | __func__); | |
d62a17ae | 298 | return; |
718e3744 | 299 | } |
d62a17ae | 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) | |
0faaabfb | 311 | zlog_debug("%s: Allowing Shortcut ABR to add new route", |
312 | __func__); | |
d62a17ae | 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; | |
718e3744 | 330 | } |
718e3744 | 331 | |
d62a17ae | 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) | |
0faaabfb | 337 | zlog_debug("%s: ERR: path type is wrong", __func__); |
d62a17ae | 338 | return; |
339 | } | |
340 | ||
341 | if (ospf->abr_type == OSPF_ABR_SHORTCUT) { | |
9d303b37 DL |
342 | if ( |
343 | or->path_type == OSPF_PATH_INTRA_AREA | |
344 | && !OSPF_IS_AREA_ID_BACKBONE( | |
345 | or->u.std.area_id)) { | |
d62a17ae | 346 | if (IS_DEBUG_OSPF_EVENT) |
347 | zlog_debug( | |
0faaabfb | 348 | "%s: Shortcut: this intra-area path is not backbone", |
349 | __func__); | |
d62a17ae | 350 | return; |
351 | } | |
352 | } else /* Not Shortcut ABR */ | |
718e3744 | 353 | { |
d62a17ae | 354 | if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { |
355 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 356 | zlog_debug("%s: route is not BB-associated", |
357 | __func__); | |
d62a17ae | 358 | return; /* We can update only BB routes */ |
359 | } | |
360 | } | |
718e3744 | 361 | |
d62a17ae | 362 | if (or->cost < cost) { |
363 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 364 | zlog_debug("%s: new route is worse", __func__); |
d62a17ae | 365 | return; |
366 | } | |
718e3744 | 367 | |
d62a17ae | 368 | if (or->cost == cost) { |
369 | if (IS_DEBUG_OSPF_EVENT) | |
370 | zlog_debug( | |
0faaabfb | 371 | "%s: new route is same distance, adding nexthops", |
372 | __func__); | |
d62a17ae | 373 | ospf_route_copy_nexthops(or, abr_or->paths); |
374 | } | |
718e3744 | 375 | |
d62a17ae | 376 | if (or->cost > cost) { |
377 | if (IS_DEBUG_OSPF_EVENT) | |
378 | zlog_debug( | |
0faaabfb | 379 | "%s: new route is better, overriding nexthops", |
380 | __func__); | |
d62a17ae | 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 | } | |
718e3744 | 396 | } |
397 | ||
d62a17ae | 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) | |
718e3744 | 403 | { |
d62a17ae | 404 | struct ospf_route * or, *abr_or, *new_or; |
405 | struct prefix_ipv4 abr; | |
d7c0a89a | 406 | uint32_t cost; |
d62a17ae | 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) | |
0faaabfb | 417 | zlog_debug("%s: can't find a route to the ABR", |
418 | __func__); | |
d62a17ae | 419 | return; |
420 | } | |
718e3744 | 421 | |
d62a17ae | 422 | cost = abr_or->cost + GET_METRIC(lsa->metric); |
718e3744 | 423 | |
d62a17ae | 424 | /* First try to find a backbone path, |
425 | because standard ABR can update only BB-associated paths */ | |
718e3744 | 426 | |
d62a17ae | 427 | if ((ospf->backbone == NULL) && (ospf->abr_type != OSPF_ABR_SHORTCUT)) |
428 | return; /* no BB area, not Shortcut ABR, exiting */ | |
718e3744 | 429 | |
d62a17ae | 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) | |
718e3744 | 435 | |
d62a17ae | 436 | /* route to ASBR through the BB not found |
437 | the router is not Shortcut ABR, exiting */ | |
718e3744 | 438 | |
d62a17ae | 439 | return; |
440 | else | |
441 | /* We're a Shortcut ABR*/ | |
718e3744 | 442 | { |
d62a17ae | 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; | |
718e3744 | 460 | } |
d62a17ae | 461 | } |
718e3744 | 462 | |
d62a17ae | 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) | |
0faaabfb | 467 | zlog_debug("%s: the remote router is not an ASBR", |
468 | __func__); | |
d62a17ae | 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; | |
d7c0a89a | 502 | uint32_t metric; |
d62a17ae | 503 | |
504 | if (lsa == NULL) | |
505 | return 0; | |
506 | ||
507 | sl = (struct summary_lsa *)lsa->data; | |
508 | ||
509 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 510 | zlog_debug("%s: LS ID: %pI4", __func__, &lsa->data->id); |
d62a17ae | 511 | metric = GET_METRIC(sl->metric); |
512 | ||
513 | if (metric == OSPF_LS_INFINITY) { | |
514 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 515 | zlog_debug("%s: metric is infinity, skip", __func__); |
d62a17ae | 516 | return 0; |
517 | } | |
518 | ||
519 | if (IS_LSA_MAXAGE(lsa)) { | |
520 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 521 | zlog_debug("%s: This LSA is too old", __func__); |
d62a17ae | 522 | return 0; |
523 | } | |
524 | ||
525 | if (ospf_lsa_is_self_originated(area->ospf, lsa)) { | |
526 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 527 | zlog_debug("%s: This LSA is mine, skip", __func__); |
d62a17ae | 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 | ||
996c9314 | 557 | LSDB_LOOP (lsdb_rt, rn, lsa) |
044506e7 | 558 | process_transit_summary_lsa(area, rt, rtrs, lsa); |
d62a17ae | 559 | } |
560 | ||
561 | void ospf_ia_routing(struct ospf *ospf, struct route_table *rt, | |
562 | struct route_table *rtrs) | |
563 | { | |
f7813c7c | 564 | struct listnode *node; |
d62a17ae | 565 | struct ospf_area *area; |
566 | ||
567 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 568 | zlog_debug("%s:start", __func__); |
d62a17ae | 569 | |
570 | if (IS_OSPF_ABR(ospf)) { | |
d62a17ae | 571 | switch (ospf->abr_type) { |
572 | case OSPF_ABR_STAND: | |
573 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 574 | zlog_debug("%s:Standard ABR", __func__); |
d62a17ae | 575 | |
576 | if ((area = ospf->backbone)) { | |
d62a17ae | 577 | if (IS_DEBUG_OSPF_EVENT) { |
578 | zlog_debug( | |
0faaabfb | 579 | "%s:backbone area found, examining summaries", |
580 | __func__); | |
d62a17ae | 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) | |
0faaabfb | 592 | zlog_debug("%s:backbone area NOT found", |
593 | __func__); | |
d62a17ae | 594 | break; |
595 | case OSPF_ABR_IBM: | |
596 | case OSPF_ABR_CISCO: | |
597 | if (IS_DEBUG_OSPF_EVENT) | |
0faaabfb | 598 | zlog_debug("%s:Alternative Cisco/IBM ABR", |
599 | __func__); | |
d62a17ae | 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( | |
0faaabfb | 606 | "%s: backbone area found, examining BB summaries", |
607 | __func__); | |
d62a17ae | 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 | |
9d303b37 | 619 | */ |
d62a17ae | 620 | if (IS_DEBUG_OSPF_EVENT) |
621 | zlog_debug( | |
0faaabfb | 622 | "%s: Active BB connection not found", |
623 | __func__); | |
d62a17ae | 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) | |
0faaabfb | 632 | zlog_debug("%s:Alternative Shortcut", __func__); |
d62a17ae | 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( | |
0faaabfb | 639 | "%s: backbone area found, examining BB summaries", |
640 | __func__); | |
d62a17ae | 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; | |
718e3744 | 659 | } |
d62a17ae | 660 | } else { |
d62a17ae | 661 | if (IS_DEBUG_OSPF_EVENT) |
0faaabfb | 662 | zlog_debug("%s:not ABR, considering all areas", |
663 | __func__); | |
d62a17ae | 664 | |
665 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) | |
666 | OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs); | |
667 | } | |
718e3744 | 668 | } |