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