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