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