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