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