/src/frr/ospfd/ospf_abr.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * OSPF ABR functions. |
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 "linklist.h" |
13 | | #include "prefix.h" |
14 | | #include "if.h" |
15 | | #include "table.h" |
16 | | #include "vty.h" |
17 | | #include "filter.h" |
18 | | #include "plist.h" |
19 | | #include "log.h" |
20 | | |
21 | | #include "ospfd/ospfd.h" |
22 | | #include "ospfd/ospf_interface.h" |
23 | | #include "ospfd/ospf_ism.h" |
24 | | #include "ospfd/ospf_asbr.h" |
25 | | #include "ospfd/ospf_lsa.h" |
26 | | #include "ospfd/ospf_lsdb.h" |
27 | | #include "ospfd/ospf_neighbor.h" |
28 | | #include "ospfd/ospf_nsm.h" |
29 | | #include "ospfd/ospf_spf.h" |
30 | | #include "ospfd/ospf_route.h" |
31 | | #include "ospfd/ospf_ia.h" |
32 | | #include "ospfd/ospf_flood.h" |
33 | | #include "ospfd/ospf_abr.h" |
34 | | #include "ospfd/ospf_ase.h" |
35 | | #include "ospfd/ospf_zebra.h" |
36 | | #include "ospfd/ospf_dump.h" |
37 | | #include "ospfd/ospf_errors.h" |
38 | | |
39 | | static struct ospf_area_range *ospf_area_range_new(struct prefix_ipv4 *p) |
40 | 0 | { |
41 | 0 | struct ospf_area_range *range; |
42 | |
|
43 | 0 | range = XCALLOC(MTYPE_OSPF_AREA_RANGE, sizeof(struct ospf_area_range)); |
44 | 0 | range->addr = p->prefix; |
45 | 0 | range->masklen = p->prefixlen; |
46 | 0 | range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; |
47 | |
|
48 | 0 | return range; |
49 | 0 | } |
50 | | |
51 | | static void ospf_area_range_free(struct ospf_area_range *range) |
52 | 0 | { |
53 | 0 | XFREE(MTYPE_OSPF_AREA_RANGE, range); |
54 | 0 | } |
55 | | |
56 | | static void ospf_area_range_add(struct ospf_area *area, |
57 | | struct route_table *ranges, |
58 | | struct ospf_area_range *range) |
59 | 0 | { |
60 | 0 | struct route_node *rn; |
61 | 0 | struct prefix_ipv4 p; |
62 | |
|
63 | 0 | p.family = AF_INET; |
64 | 0 | p.prefixlen = range->masklen; |
65 | 0 | p.prefix = range->addr; |
66 | 0 | apply_mask_ipv4(&p); |
67 | |
|
68 | 0 | rn = route_node_get(ranges, (struct prefix *)&p); |
69 | 0 | if (rn->info) { |
70 | 0 | route_unlock_node(rn); |
71 | 0 | ospf_area_range_free(rn->info); |
72 | 0 | rn->info = range; |
73 | 0 | } else |
74 | 0 | rn->info = range; |
75 | 0 | } |
76 | | |
77 | | static void ospf_area_range_delete(struct ospf_area *area, |
78 | | struct route_node *rn) |
79 | 0 | { |
80 | 0 | struct ospf_area_range *range = rn->info; |
81 | 0 | bool nssa = CHECK_FLAG(range->flags, OSPF_AREA_RANGE_NSSA); |
82 | |
|
83 | 0 | if (ospf_area_range_active(range) && |
84 | 0 | CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE)) |
85 | 0 | ospf_delete_discard_route(area->ospf, area->ospf->new_table, |
86 | 0 | (struct prefix_ipv4 *)&rn->p, nssa); |
87 | |
|
88 | 0 | ospf_area_range_free(range); |
89 | 0 | rn->info = NULL; |
90 | 0 | route_unlock_node(rn); |
91 | 0 | route_unlock_node(rn); |
92 | 0 | } |
93 | | |
94 | | struct ospf_area_range *ospf_area_range_lookup(struct ospf_area *area, |
95 | | struct route_table *ranges, |
96 | | struct prefix_ipv4 *p) |
97 | 0 | { |
98 | 0 | struct route_node *rn; |
99 | |
|
100 | 0 | rn = route_node_lookup(ranges, (struct prefix *)p); |
101 | 0 | if (rn) { |
102 | 0 | route_unlock_node(rn); |
103 | 0 | return rn->info; |
104 | 0 | } |
105 | 0 | return NULL; |
106 | 0 | } |
107 | | |
108 | | struct ospf_area_range *ospf_area_range_lookup_next(struct ospf_area *area, |
109 | | struct in_addr *range_net, |
110 | | int first) |
111 | 0 | { |
112 | 0 | struct route_node *rn; |
113 | 0 | struct prefix_ipv4 p; |
114 | 0 | struct ospf_area_range *find; |
115 | |
|
116 | 0 | p.family = AF_INET; |
117 | 0 | p.prefixlen = IPV4_MAX_BITLEN; |
118 | 0 | p.prefix = *range_net; |
119 | 0 | apply_mask_ipv4(&p); |
120 | |
|
121 | 0 | if (first) |
122 | 0 | rn = route_top(area->ranges); |
123 | 0 | else { |
124 | 0 | rn = route_node_get(area->ranges, (struct prefix *)&p); |
125 | 0 | rn = route_next(rn); |
126 | 0 | } |
127 | |
|
128 | 0 | for (; rn; rn = route_next(rn)) |
129 | 0 | if (rn->info) |
130 | 0 | break; |
131 | |
|
132 | 0 | if (rn && rn->info) { |
133 | 0 | find = rn->info; |
134 | 0 | *range_net = rn->p.u.prefix4; |
135 | 0 | route_unlock_node(rn); |
136 | 0 | return find; |
137 | 0 | } |
138 | 0 | return NULL; |
139 | 0 | } |
140 | | |
141 | | static struct ospf_area_range *ospf_area_range_match(struct ospf_area *area, |
142 | | struct route_table *ranges, |
143 | | struct prefix_ipv4 *p) |
144 | 0 | { |
145 | 0 | struct route_node *node; |
146 | |
|
147 | 0 | node = route_node_match(ranges, (struct prefix *)p); |
148 | 0 | if (node) { |
149 | 0 | route_unlock_node(node); |
150 | 0 | return node->info; |
151 | 0 | } |
152 | 0 | return NULL; |
153 | 0 | } |
154 | | |
155 | | struct ospf_area_range *ospf_area_range_match_any(struct ospf *ospf, |
156 | | struct prefix_ipv4 *p) |
157 | 0 | { |
158 | 0 | struct ospf_area_range *range; |
159 | 0 | struct ospf_area *area; |
160 | 0 | struct listnode *node; |
161 | |
|
162 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) |
163 | 0 | if ((range = ospf_area_range_match(area, area->ranges, p))) |
164 | 0 | return range; |
165 | | |
166 | 0 | return NULL; |
167 | 0 | } |
168 | | |
169 | | int ospf_area_range_active(struct ospf_area_range *range) |
170 | 0 | { |
171 | 0 | return range->specifics; |
172 | 0 | } |
173 | | |
174 | | static int ospf_area_actively_attached(struct ospf_area *area) |
175 | 0 | { |
176 | 0 | return area->act_ints; |
177 | 0 | } |
178 | | |
179 | | int ospf_area_range_set(struct ospf *ospf, struct ospf_area *area, |
180 | | struct route_table *ranges, struct prefix_ipv4 *p, |
181 | | int advertise, bool nssa) |
182 | 0 | { |
183 | 0 | struct ospf_area_range *range; |
184 | |
|
185 | 0 | range = ospf_area_range_lookup(area, ranges, p); |
186 | 0 | if (range != NULL) { |
187 | 0 | if (!CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) |
188 | 0 | range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; |
189 | 0 | if ((CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) |
190 | 0 | && !CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) |
191 | 0 | || (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) |
192 | 0 | && CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE))) |
193 | 0 | ospf_schedule_abr_task(ospf); |
194 | 0 | } else { |
195 | 0 | range = ospf_area_range_new(p); |
196 | 0 | ospf_area_range_add(area, ranges, range); |
197 | 0 | ospf_schedule_abr_task(ospf); |
198 | 0 | } |
199 | |
|
200 | 0 | if (CHECK_FLAG(advertise, OSPF_AREA_RANGE_ADVERTISE)) |
201 | 0 | SET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); |
202 | 0 | else { |
203 | 0 | UNSET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); |
204 | 0 | range->cost_config = OSPF_AREA_RANGE_COST_UNSPEC; |
205 | 0 | } |
206 | |
|
207 | 0 | if (nssa) |
208 | 0 | SET_FLAG(range->flags, OSPF_AREA_RANGE_NSSA); |
209 | |
|
210 | 0 | return 1; |
211 | 0 | } |
212 | | |
213 | | int ospf_area_range_cost_set(struct ospf *ospf, struct ospf_area *area, |
214 | | struct route_table *ranges, struct prefix_ipv4 *p, |
215 | | uint32_t cost) |
216 | 0 | { |
217 | 0 | struct ospf_area_range *range; |
218 | |
|
219 | 0 | range = ospf_area_range_lookup(area, ranges, p); |
220 | 0 | if (range == NULL) |
221 | 0 | return 0; |
222 | | |
223 | 0 | if (range->cost_config != cost) { |
224 | 0 | range->cost_config = cost; |
225 | 0 | if (ospf_area_range_active(range)) |
226 | 0 | ospf_schedule_abr_task(ospf); |
227 | 0 | } |
228 | |
|
229 | 0 | return 1; |
230 | 0 | } |
231 | | |
232 | | int ospf_area_range_unset(struct ospf *ospf, struct ospf_area *area, |
233 | | struct route_table *ranges, struct prefix_ipv4 *p) |
234 | 0 | { |
235 | 0 | struct route_node *rn; |
236 | |
|
237 | 0 | rn = route_node_lookup(ranges, (struct prefix *)p); |
238 | 0 | if (rn == NULL) |
239 | 0 | return 0; |
240 | | |
241 | 0 | if (ospf_area_range_active(rn->info)) |
242 | 0 | ospf_schedule_abr_task(ospf); |
243 | |
|
244 | 0 | ospf_area_range_delete(area, rn); |
245 | |
|
246 | 0 | return 1; |
247 | 0 | } |
248 | | |
249 | | int ospf_area_range_substitute_set(struct ospf *ospf, struct ospf_area *area, |
250 | | struct prefix_ipv4 *p, struct prefix_ipv4 *s) |
251 | 0 | { |
252 | 0 | struct ospf_area_range *range; |
253 | |
|
254 | 0 | range = ospf_area_range_lookup(area, area->ranges, p); |
255 | |
|
256 | 0 | if (range != NULL) { |
257 | 0 | if (!CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE) |
258 | 0 | || !CHECK_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) |
259 | 0 | ospf_schedule_abr_task(ospf); |
260 | 0 | } else { |
261 | 0 | range = ospf_area_range_new(p); |
262 | 0 | ospf_area_range_add(area, area->ranges, range); |
263 | 0 | ospf_schedule_abr_task(ospf); |
264 | 0 | } |
265 | |
|
266 | 0 | SET_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE); |
267 | 0 | SET_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE); |
268 | 0 | range->subst_addr = s->prefix; |
269 | 0 | range->subst_masklen = s->prefixlen; |
270 | |
|
271 | 0 | return 1; |
272 | 0 | } |
273 | | |
274 | | int ospf_area_range_substitute_unset(struct ospf *ospf, struct ospf_area *area, |
275 | | struct prefix_ipv4 *p) |
276 | 0 | { |
277 | 0 | struct ospf_area_range *range; |
278 | |
|
279 | 0 | range = ospf_area_range_lookup(area, area->ranges, p); |
280 | 0 | if (range == NULL) |
281 | 0 | return 0; |
282 | | |
283 | 0 | if (CHECK_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE)) |
284 | 0 | if (ospf_area_range_active(range)) |
285 | 0 | ospf_schedule_abr_task(ospf); |
286 | |
|
287 | 0 | UNSET_FLAG(range->flags, OSPF_AREA_RANGE_SUBSTITUTE); |
288 | 0 | range->subst_addr.s_addr = INADDR_ANY; |
289 | 0 | range->subst_masklen = 0; |
290 | |
|
291 | 0 | return 1; |
292 | 0 | } |
293 | | |
294 | | int ospf_act_bb_connection(struct ospf *ospf) |
295 | 0 | { |
296 | 0 | struct ospf_interface *oi; |
297 | 0 | struct listnode *node; |
298 | 0 | int full_nbrs = 0; |
299 | |
|
300 | 0 | if (ospf->backbone == NULL) |
301 | 0 | return 0; |
302 | | |
303 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->backbone->oiflist, node, oi)) { |
304 | 0 | struct ospf_neighbor *nbr; |
305 | 0 | struct route_node *rn; |
306 | |
|
307 | 0 | for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { |
308 | 0 | nbr = rn->info; |
309 | 0 | if (!nbr) |
310 | 0 | continue; |
311 | | |
312 | 0 | if (nbr->state == NSM_Full |
313 | 0 | || OSPF_GR_IS_ACTIVE_HELPER(nbr)) |
314 | 0 | full_nbrs++; |
315 | 0 | } |
316 | 0 | } |
317 | |
|
318 | 0 | return full_nbrs; |
319 | 0 | } |
320 | | |
321 | | /* Determine whether this router is elected translator or not for area */ |
322 | | static int ospf_abr_nssa_am_elected(struct ospf_area *area) |
323 | 0 | { |
324 | 0 | struct route_node *rn; |
325 | 0 | struct ospf_lsa *lsa; |
326 | 0 | struct router_lsa *rlsa; |
327 | 0 | struct in_addr *best = NULL; |
328 | |
|
329 | 0 | LSDB_LOOP (ROUTER_LSDB(area), rn, lsa) { |
330 | | /* sanity checks */ |
331 | 0 | if (!lsa || (lsa->data->type != OSPF_ROUTER_LSA) |
332 | 0 | || IS_LSA_SELF(lsa)) |
333 | 0 | continue; |
334 | | |
335 | 0 | rlsa = (struct router_lsa *)lsa->data; |
336 | | |
337 | | /* ignore non-ABR routers */ |
338 | 0 | if (!IS_ROUTER_LSA_BORDER(rlsa)) |
339 | 0 | continue; |
340 | | |
341 | | /* Router has Nt flag - always translate */ |
342 | 0 | if (IS_ROUTER_LSA_NT(rlsa)) { |
343 | 0 | if (IS_DEBUG_OSPF_NSSA) |
344 | 0 | zlog_debug("%s: router %pI4 asserts Nt", |
345 | 0 | __func__, &lsa->data->id); |
346 | 0 | return 0; |
347 | 0 | } |
348 | | |
349 | 0 | if (best == NULL) |
350 | 0 | best = &lsa->data->id; |
351 | 0 | else if (IPV4_ADDR_CMP(&best->s_addr, &lsa->data->id.s_addr) |
352 | 0 | < 0) |
353 | 0 | best = &lsa->data->id; |
354 | 0 | } |
355 | | |
356 | 0 | if (IS_DEBUG_OSPF_NSSA) |
357 | 0 | zlog_debug("%s: best electable ABR is: %pI4", __func__, best); |
358 | |
|
359 | 0 | if (best == NULL) |
360 | 0 | return 1; |
361 | | |
362 | 0 | if (IPV4_ADDR_CMP(&best->s_addr, &area->ospf->router_id.s_addr) < 0) |
363 | 0 | return 1; |
364 | 0 | else |
365 | 0 | return 0; |
366 | 0 | } |
367 | | |
368 | | /* Check NSSA ABR status |
369 | | * assumes there are nssa areas |
370 | | */ |
371 | | void ospf_abr_nssa_check_status(struct ospf *ospf) |
372 | 0 | { |
373 | 0 | struct ospf_area *area; |
374 | 0 | struct listnode *lnode, *nnode; |
375 | |
|
376 | 0 | for (ALL_LIST_ELEMENTS(ospf->areas, lnode, nnode, area)) { |
377 | 0 | uint8_t old_state = area->NSSATranslatorState; |
378 | |
|
379 | 0 | if (area->external_routing != OSPF_AREA_NSSA) |
380 | 0 | continue; |
381 | | |
382 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
383 | 0 | zlog_debug("%s: checking area %pI4", __func__, |
384 | 0 | &area->area_id); |
385 | |
|
386 | 0 | if (!IS_OSPF_ABR(area->ospf)) { |
387 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
388 | 0 | zlog_debug("%s: not ABR", __func__); |
389 | 0 | area->NSSATranslatorState = |
390 | 0 | OSPF_NSSA_TRANSLATE_DISABLED; |
391 | 0 | } else { |
392 | 0 | switch (area->NSSATranslatorRole) { |
393 | 0 | case OSPF_NSSA_ROLE_NEVER: |
394 | | /* We never Translate Type-7 LSA. */ |
395 | | /* TODO: check previous state and flush? */ |
396 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
397 | 0 | zlog_debug("%s: never translate", |
398 | 0 | __func__); |
399 | 0 | area->NSSATranslatorState = |
400 | 0 | OSPF_NSSA_TRANSLATE_DISABLED; |
401 | 0 | break; |
402 | | |
403 | 0 | case OSPF_NSSA_ROLE_ALWAYS: |
404 | | /* We always translate if we are an ABR |
405 | | * TODO: originate new LSAs if state change? |
406 | | * or let the nssa abr task take care of it? |
407 | | */ |
408 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
409 | 0 | zlog_debug("%s: translate always", |
410 | 0 | __func__); |
411 | 0 | area->NSSATranslatorState = |
412 | 0 | OSPF_NSSA_TRANSLATE_ENABLED; |
413 | 0 | break; |
414 | | |
415 | 0 | case OSPF_NSSA_ROLE_CANDIDATE: |
416 | | /* We are a candidate for Translation */ |
417 | 0 | if (ospf_abr_nssa_am_elected(area) > 0) { |
418 | 0 | area->NSSATranslatorState = |
419 | 0 | OSPF_NSSA_TRANSLATE_ENABLED; |
420 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
421 | 0 | zlog_debug( |
422 | 0 | "%s: elected translator", |
423 | 0 | __func__); |
424 | 0 | } else { |
425 | 0 | area->NSSATranslatorState = |
426 | 0 | OSPF_NSSA_TRANSLATE_DISABLED; |
427 | 0 | if (IS_DEBUG_OSPF(nssa, NSSA)) |
428 | 0 | zlog_debug("%s: not elected", |
429 | 0 | __func__); |
430 | 0 | } |
431 | 0 | break; |
432 | 0 | } |
433 | 0 | } |
434 | | /* RFC3101, 3.1: |
435 | | * All NSSA border routers must set the E-bit in the Type-1 |
436 | | * router-LSAs |
437 | | * of their directly attached non-stub areas, even when they are |
438 | | * not |
439 | | * translating. |
440 | | */ |
441 | 0 | if (old_state != area->NSSATranslatorState) { |
442 | 0 | if (old_state == OSPF_NSSA_TRANSLATE_DISABLED) |
443 | 0 | ospf_asbr_status_update(ospf, |
444 | 0 | ++ospf->redistribute); |
445 | 0 | else if (area->NSSATranslatorState |
446 | 0 | == OSPF_NSSA_TRANSLATE_DISABLED) |
447 | 0 | ospf_asbr_status_update(ospf, |
448 | 0 | --ospf->redistribute); |
449 | 0 | } |
450 | 0 | } |
451 | 0 | } |
452 | | |
453 | | /* Check area border router status. */ |
454 | | void ospf_check_abr_status(struct ospf *ospf) |
455 | 0 | { |
456 | 0 | struct ospf_area *area; |
457 | 0 | struct listnode *node, *nnode; |
458 | 0 | int bb_configured = 0; |
459 | 0 | int bb_act_attached = 0; |
460 | 0 | int areas_configured = 0; |
461 | 0 | int areas_act_attached = 0; |
462 | 0 | uint8_t new_flags = ospf->flags; |
463 | |
|
464 | 0 | if (IS_DEBUG_OSPF_EVENT) |
465 | 0 | zlog_debug("%s: Start", __func__); |
466 | |
|
467 | 0 | for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { |
468 | 0 | if (listcount(area->oiflist)) { |
469 | 0 | areas_configured++; |
470 | |
|
471 | 0 | if (OSPF_IS_AREA_BACKBONE(area)) |
472 | 0 | bb_configured = 1; |
473 | 0 | } |
474 | |
|
475 | 0 | if (ospf_area_actively_attached(area)) { |
476 | 0 | areas_act_attached++; |
477 | |
|
478 | 0 | if (OSPF_IS_AREA_BACKBONE(area)) |
479 | 0 | bb_act_attached = 1; |
480 | 0 | } |
481 | 0 | } |
482 | |
|
483 | 0 | if (IS_DEBUG_OSPF_EVENT) { |
484 | 0 | zlog_debug("%s: looked through areas", __func__); |
485 | 0 | zlog_debug("%s: bb_configured: %d", __func__, bb_configured); |
486 | 0 | zlog_debug("%s: bb_act_attached: %d", __func__, |
487 | 0 | bb_act_attached); |
488 | 0 | zlog_debug("%s: areas_configured: %d", __func__, |
489 | 0 | areas_configured); |
490 | 0 | zlog_debug("%s: areas_act_attached: %d", __func__, |
491 | 0 | areas_act_attached); |
492 | 0 | } |
493 | |
|
494 | 0 | switch (ospf->abr_type) { |
495 | 0 | case OSPF_ABR_SHORTCUT: |
496 | 0 | case OSPF_ABR_STAND: |
497 | 0 | if (areas_act_attached > 1) |
498 | 0 | SET_FLAG(new_flags, OSPF_FLAG_ABR); |
499 | 0 | else |
500 | 0 | UNSET_FLAG(new_flags, OSPF_FLAG_ABR); |
501 | 0 | break; |
502 | | |
503 | 0 | case OSPF_ABR_IBM: |
504 | 0 | if ((areas_act_attached > 1) && bb_configured) |
505 | 0 | SET_FLAG(new_flags, OSPF_FLAG_ABR); |
506 | 0 | else |
507 | 0 | UNSET_FLAG(new_flags, OSPF_FLAG_ABR); |
508 | 0 | break; |
509 | | |
510 | 0 | case OSPF_ABR_CISCO: |
511 | 0 | if ((areas_configured > 1) && bb_act_attached) |
512 | 0 | SET_FLAG(new_flags, OSPF_FLAG_ABR); |
513 | 0 | else |
514 | 0 | UNSET_FLAG(new_flags, OSPF_FLAG_ABR); |
515 | 0 | break; |
516 | 0 | default: |
517 | 0 | break; |
518 | 0 | } |
519 | | |
520 | 0 | if (new_flags != ospf->flags) { |
521 | 0 | ospf_spf_calculate_schedule(ospf, SPF_FLAG_ABR_STATUS_CHANGE); |
522 | 0 | if (IS_DEBUG_OSPF_EVENT) |
523 | 0 | zlog_debug("%s: new router flags: %x", __func__, |
524 | 0 | new_flags); |
525 | 0 | ospf->flags = new_flags; |
526 | 0 | ospf_router_lsa_update(ospf); |
527 | 0 | } |
528 | 0 | } |
529 | | |
530 | | static void ospf_abr_update_aggregate(struct ospf_area_range *range, |
531 | | uint32_t cost, struct ospf_area *area) |
532 | 0 | { |
533 | 0 | if (IS_DEBUG_OSPF_EVENT) |
534 | 0 | zlog_debug("%s: Start", __func__); |
535 | |
|
536 | 0 | if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED) |
537 | 0 | && (range->cost != OSPF_STUB_MAX_METRIC_SUMMARY_COST)) { |
538 | 0 | range->cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; |
539 | 0 | if (IS_DEBUG_OSPF_EVENT) |
540 | 0 | zlog_debug("%s: use summary max-metric 0x%08x", |
541 | 0 | __func__, range->cost); |
542 | 0 | } else if (range->cost_config != OSPF_AREA_RANGE_COST_UNSPEC) { |
543 | 0 | if (IS_DEBUG_OSPF_EVENT) |
544 | 0 | zlog_debug("%s: use configured cost %d", __func__, |
545 | 0 | range->cost_config); |
546 | |
|
547 | 0 | range->cost = range->cost_config; |
548 | 0 | } else { |
549 | 0 | if (!ospf_area_range_active(range)) { |
550 | 0 | if (IS_DEBUG_OSPF_EVENT) |
551 | 0 | zlog_debug("%s: use cost %d", __func__, cost); |
552 | |
|
553 | 0 | range->cost = cost; /* 1st time get 1st cost */ |
554 | 0 | } |
555 | |
|
556 | 0 | if (cost > range->cost) { |
557 | 0 | if (IS_DEBUG_OSPF_EVENT) |
558 | 0 | zlog_debug("%s: update to %d", __func__, cost); |
559 | |
|
560 | 0 | range->cost = cost; |
561 | 0 | } |
562 | 0 | } |
563 | |
|
564 | 0 | range->specifics++; |
565 | 0 | } |
566 | | |
567 | | static void set_metric(struct ospf_lsa *lsa, uint32_t metric) |
568 | 0 | { |
569 | 0 | struct summary_lsa *header; |
570 | 0 | uint8_t *mp; |
571 | 0 | metric = htonl(metric); |
572 | 0 | mp = (uint8_t *)&metric; |
573 | 0 | mp++; |
574 | 0 | header = (struct summary_lsa *)lsa->data; |
575 | 0 | memcpy(header->metric, mp, 3); |
576 | 0 | } |
577 | | |
578 | | /* ospf_abr_translate_nssa */ |
579 | | static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa) |
580 | 0 | { |
581 | | /* Incoming Type-7 or later aggregated Type-7 |
582 | | * |
583 | | * LSA is skipped if P-bit is off. |
584 | | * LSA is aggregated if within range. |
585 | | * |
586 | | * The Type-7 is translated, Installed/Approved as a Type-5 into |
587 | | * global LSDB, then Flooded through AS |
588 | | * |
589 | | * Later, any Unapproved Translated Type-5's are flushed/discarded |
590 | | */ |
591 | |
|
592 | 0 | struct ospf_lsa *old = NULL, *new = NULL; |
593 | 0 | struct as_external_lsa *ext7; |
594 | 0 | struct prefix_ipv4 p; |
595 | 0 | struct ospf_area_range *range; |
596 | |
|
597 | 0 | if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) { |
598 | 0 | if (IS_DEBUG_OSPF_NSSA) |
599 | 0 | zlog_debug("%s: LSA Id %pI4, P-bit off, NO Translation", |
600 | 0 | __func__, &lsa->data->id); |
601 | 0 | return 1; |
602 | 0 | } |
603 | | |
604 | 0 | if (IS_DEBUG_OSPF_NSSA) |
605 | 0 | zlog_debug("%s: LSA Id %pI4, TRANSLATING 7 to 5", __func__, |
606 | 0 | &lsa->data->id); |
607 | |
|
608 | 0 | ext7 = (struct as_external_lsa *)(lsa->data); |
609 | 0 | p.prefix = lsa->data->id; |
610 | 0 | p.prefixlen = ip_masklen(ext7->mask); |
611 | |
|
612 | 0 | if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION) { |
613 | 0 | if (IS_DEBUG_OSPF_NSSA) |
614 | 0 | zlog_debug( |
615 | 0 | "%s: LSA Id %pI4, Forward address is 0, NO Translation", |
616 | 0 | __func__, &lsa->data->id); |
617 | 0 | return 1; |
618 | 0 | } |
619 | | |
620 | | /* try find existing AS-External LSA for this prefix */ |
621 | 0 | old = ospf_external_info_find_lsa(area->ospf, &p); |
622 | |
|
623 | 0 | if (CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) { |
624 | | /* if type-7 is removed, remove old translated type-5 lsa */ |
625 | 0 | if (old) { |
626 | 0 | UNSET_FLAG(old->flags, OSPF_LSA_APPROVED); |
627 | 0 | if (IS_DEBUG_OSPF_NSSA) |
628 | 0 | zlog_debug( |
629 | 0 | "%s: remove old translated LSA id %pI4", |
630 | 0 | __func__, &old->data->id); |
631 | 0 | } |
632 | | /* if type-7 is removed and type-5 does not exist, do not |
633 | | * originate */ |
634 | 0 | return 1; |
635 | 0 | } |
636 | | |
637 | 0 | range = ospf_area_range_match(area, area->nssa_ranges, &p); |
638 | 0 | if (range) { |
639 | 0 | if (IS_DEBUG_OSPF_NSSA) |
640 | 0 | zlog_debug("Suppressed by range %pI4/%u of area %pI4", |
641 | 0 | &range->addr, range->masklen, |
642 | 0 | &area->area_id); |
643 | |
|
644 | 0 | ospf_abr_update_aggregate(range, GET_METRIC(ext7->e[0].metric), |
645 | 0 | area); |
646 | 0 | return 1; |
647 | 0 | } |
648 | | |
649 | 0 | if (old && CHECK_FLAG(old->flags, OSPF_LSA_APPROVED)) { |
650 | 0 | if (IS_DEBUG_OSPF_NSSA) |
651 | 0 | zlog_debug( |
652 | 0 | "%s: found old translated LSA Id %pI4, refreshing", |
653 | 0 | __func__, &old->data->id); |
654 | | |
655 | | /* refresh */ |
656 | 0 | new = ospf_translated_nssa_refresh(area->ospf, lsa, old); |
657 | 0 | if (!new) { |
658 | 0 | if (IS_DEBUG_OSPF_NSSA) |
659 | 0 | zlog_debug( |
660 | 0 | "%s: could not refresh translated LSA Id %pI4", |
661 | 0 | __func__, &old->data->id); |
662 | 0 | } |
663 | 0 | } else { |
664 | | /* no existing external route for this LSA Id |
665 | | * originate translated LSA |
666 | | */ |
667 | |
|
668 | 0 | if (ospf_translated_nssa_originate(area->ospf, lsa, old) |
669 | 0 | == NULL) { |
670 | 0 | if (IS_DEBUG_OSPF_NSSA) |
671 | 0 | zlog_debug( |
672 | 0 | "%s: Could not translate Type-7 for %pI4 to Type-5", |
673 | 0 | __func__, &lsa->data->id); |
674 | 0 | return 1; |
675 | 0 | } |
676 | 0 | } |
677 | | |
678 | 0 | return 0; |
679 | 0 | } |
680 | | |
681 | | static void ospf_abr_translate_nssa_range(struct ospf *ospf, |
682 | | struct prefix_ipv4 *p, uint32_t cost) |
683 | 0 | { |
684 | 0 | struct external_info ei = {}; |
685 | 0 | struct ospf_lsa *lsa; |
686 | |
|
687 | 0 | prefix_copy(&ei.p, p); |
688 | 0 | ei.type = ZEBRA_ROUTE_OSPF; |
689 | 0 | ei.route_map_set.metric = cost; |
690 | 0 | ei.route_map_set.metric_type = -1; |
691 | |
|
692 | 0 | lsa = ospf_external_info_find_lsa(ospf, p); |
693 | 0 | if (lsa) |
694 | 0 | lsa = ospf_external_lsa_refresh(ospf, lsa, &ei, |
695 | 0 | LSA_REFRESH_FORCE, true); |
696 | 0 | else |
697 | 0 | lsa = ospf_external_lsa_originate(ospf, &ei); |
698 | 0 | SET_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT); |
699 | 0 | } |
700 | | |
701 | | void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost, |
702 | | struct ospf_area *area) |
703 | 0 | { |
704 | 0 | struct ospf_lsa *lsa, *old = NULL; |
705 | 0 | struct summary_lsa *sl = NULL; |
706 | 0 | uint32_t full_cost; |
707 | |
|
708 | 0 | if (IS_DEBUG_OSPF_EVENT) |
709 | 0 | zlog_debug("%s: Start", __func__); |
710 | |
|
711 | 0 | if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) |
712 | 0 | full_cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST; |
713 | 0 | else |
714 | 0 | full_cost = cost; |
715 | |
|
716 | 0 | old = ospf_lsa_lookup_by_prefix(area->lsdb, OSPF_SUMMARY_LSA, p, |
717 | 0 | area->ospf->router_id); |
718 | 0 | if (old) { |
719 | 0 | if (IS_DEBUG_OSPF_EVENT) |
720 | 0 | zlog_debug("%s: old summary found", __func__); |
721 | |
|
722 | 0 | sl = (struct summary_lsa *)old->data; |
723 | |
|
724 | 0 | if (IS_DEBUG_OSPF_EVENT) |
725 | 0 | zlog_debug("%s: old metric: %d, new metric: %d", |
726 | 0 | __func__, GET_METRIC(sl->metric), cost); |
727 | |
|
728 | 0 | if ((GET_METRIC(sl->metric) == full_cost) |
729 | 0 | && ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) { |
730 | | /* unchanged. simply reapprove it */ |
731 | 0 | if (IS_DEBUG_OSPF_EVENT) |
732 | 0 | zlog_debug("%s: old summary approved", |
733 | 0 | __func__); |
734 | 0 | SET_FLAG(old->flags, OSPF_LSA_APPROVED); |
735 | 0 | } else { |
736 | | /* LSA is changed, refresh it */ |
737 | 0 | if (IS_DEBUG_OSPF_EVENT) |
738 | 0 | zlog_debug("%s: refreshing summary", __func__); |
739 | 0 | set_metric(old, full_cost); |
740 | 0 | lsa = ospf_lsa_refresh(area->ospf, old); |
741 | |
|
742 | 0 | if (!lsa) { |
743 | 0 | flog_warn(EC_OSPF_LSA_MISSING, |
744 | 0 | "%s: Could not refresh %pFX to %pI4", |
745 | 0 | __func__, (struct prefix *)p, |
746 | 0 | &area->area_id); |
747 | 0 | return; |
748 | 0 | } |
749 | | |
750 | 0 | SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
751 | | /* This will flood through area. */ |
752 | 0 | } |
753 | 0 | } else { |
754 | 0 | if (IS_DEBUG_OSPF_EVENT) |
755 | 0 | zlog_debug("%s: creating new summary", __func__); |
756 | 0 | lsa = ospf_summary_lsa_originate(p, full_cost, area); |
757 | | /* This will flood through area. */ |
758 | |
|
759 | 0 | if (!lsa) { |
760 | 0 | flog_warn(EC_OSPF_LSA_MISSING, |
761 | 0 | "%s: Could not originate %pFX to %pi4", |
762 | 0 | __func__, (struct prefix *)p, |
763 | 0 | &area->area_id); |
764 | 0 | return; |
765 | 0 | } |
766 | | |
767 | 0 | SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
768 | 0 | if (IS_DEBUG_OSPF_EVENT) |
769 | 0 | zlog_debug("%s: flooding new version of summary", |
770 | 0 | __func__); |
771 | 0 | } |
772 | | |
773 | 0 | if (IS_DEBUG_OSPF_EVENT) |
774 | 0 | zlog_debug("%s: Stop", __func__); |
775 | 0 | } |
776 | | |
777 | | static int ospf_abr_nexthops_belong_to_area(struct ospf_route * or, |
778 | | struct ospf_area *area) |
779 | 0 | { |
780 | 0 | struct listnode *node, *nnode; |
781 | 0 | struct ospf_path *path; |
782 | 0 | struct ospf_interface *oi; |
783 | |
|
784 | 0 | for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) |
785 | 0 | for (ALL_LIST_ELEMENTS_RO(area->oiflist, nnode, oi)) |
786 | 0 | if (oi->ifp && oi->ifp->ifindex == path->ifindex) |
787 | 0 | return 1; |
788 | | |
789 | 0 | return 0; |
790 | 0 | } |
791 | | |
792 | | static int ospf_abr_should_accept(struct prefix_ipv4 *p, struct ospf_area *area) |
793 | 0 | { |
794 | 0 | if (IMPORT_NAME(area)) { |
795 | 0 | if (IMPORT_LIST(area) == NULL) |
796 | 0 | IMPORT_LIST(area) = |
797 | 0 | access_list_lookup(AFI_IP, IMPORT_NAME(area)); |
798 | |
|
799 | 0 | if (IMPORT_LIST(area)) |
800 | 0 | if (access_list_apply(IMPORT_LIST(area), p) |
801 | 0 | == FILTER_DENY) |
802 | 0 | return 0; |
803 | 0 | } |
804 | | |
805 | 0 | return 1; |
806 | 0 | } |
807 | | |
808 | | static int ospf_abr_plist_in_check(struct ospf_area *area, |
809 | | struct ospf_route * or, |
810 | | struct prefix_ipv4 *p) |
811 | 0 | { |
812 | 0 | if (PREFIX_NAME_IN(area)) { |
813 | 0 | if (PREFIX_LIST_IN(area) == NULL) |
814 | 0 | PREFIX_LIST_IN(area) = prefix_list_lookup( |
815 | 0 | AFI_IP, PREFIX_NAME_IN(area)); |
816 | 0 | if (PREFIX_LIST_IN(area)) |
817 | 0 | if (prefix_list_apply(PREFIX_LIST_IN(area), p) |
818 | 0 | != PREFIX_PERMIT) |
819 | 0 | return 0; |
820 | 0 | } |
821 | 0 | return 1; |
822 | 0 | } |
823 | | |
824 | | static int ospf_abr_plist_out_check(struct ospf_area *area, |
825 | | struct ospf_route * or, |
826 | | struct prefix_ipv4 *p) |
827 | 0 | { |
828 | 0 | if (PREFIX_NAME_OUT(area)) { |
829 | 0 | if (PREFIX_LIST_OUT(area) == NULL) |
830 | 0 | PREFIX_LIST_OUT(area) = prefix_list_lookup( |
831 | 0 | AFI_IP, PREFIX_NAME_OUT(area)); |
832 | 0 | if (PREFIX_LIST_OUT(area)) |
833 | 0 | if (prefix_list_apply(PREFIX_LIST_OUT(area), p) |
834 | 0 | != PREFIX_PERMIT) |
835 | 0 | return 0; |
836 | 0 | } |
837 | 0 | return 1; |
838 | 0 | } |
839 | | |
840 | | static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p, |
841 | | struct ospf_route * or) |
842 | 0 | { |
843 | 0 | struct ospf_area_range *range; |
844 | 0 | struct ospf_area *area, *or_area; |
845 | 0 | struct listnode *node; |
846 | |
|
847 | 0 | if (IS_DEBUG_OSPF_EVENT) |
848 | 0 | zlog_debug("%s: Start", __func__); |
849 | |
|
850 | 0 | or_area = ospf_area_lookup_by_area_id(ospf, or->u.std.area_id); |
851 | 0 | assert(or_area); |
852 | |
|
853 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
854 | 0 | if (IS_DEBUG_OSPF_EVENT) |
855 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
856 | 0 | &area->area_id); |
857 | |
|
858 | 0 | if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)) |
859 | 0 | continue; |
860 | | |
861 | 0 | if (ospf_abr_nexthops_belong_to_area(or, area)) |
862 | 0 | continue; |
863 | | |
864 | 0 | if (!ospf_abr_should_accept(p, area)) { |
865 | 0 | if (IS_DEBUG_OSPF_EVENT) |
866 | 0 | zlog_debug( |
867 | 0 | "%s: prefix %pFX was denied by import-list", |
868 | 0 | __func__, p); |
869 | 0 | continue; |
870 | 0 | } |
871 | | |
872 | 0 | if (!ospf_abr_plist_in_check(area, or, p)) { |
873 | 0 | if (IS_DEBUG_OSPF_EVENT) |
874 | 0 | zlog_debug( |
875 | 0 | "%s: prefix %pFX was denied by prefix-list", |
876 | 0 | __func__, p); |
877 | 0 | continue; |
878 | 0 | } |
879 | | |
880 | 0 | if (area->external_routing != OSPF_AREA_DEFAULT |
881 | 0 | && area->no_summary) { |
882 | 0 | if (IS_DEBUG_OSPF_EVENT) |
883 | 0 | zlog_debug( |
884 | 0 | "%s: area %pI4 is stub and no_summary", |
885 | 0 | __func__, &area->area_id); |
886 | 0 | continue; |
887 | 0 | } |
888 | | |
889 | 0 | if (or->path_type == OSPF_PATH_INTER_AREA) { |
890 | 0 | if (IS_DEBUG_OSPF_EVENT) |
891 | 0 | zlog_debug( |
892 | 0 | "%s: this is inter-area route to %pFX", |
893 | 0 | __func__, p); |
894 | |
|
895 | 0 | if (!OSPF_IS_AREA_BACKBONE(area)) |
896 | 0 | ospf_abr_announce_network_to_area(p, or->cost, |
897 | 0 | area); |
898 | 0 | } |
899 | |
|
900 | 0 | if (or->path_type == OSPF_PATH_INTRA_AREA) { |
901 | 0 | if (IS_DEBUG_OSPF_EVENT) |
902 | 0 | zlog_debug( |
903 | 0 | "%s: this is intra-area route to %pFX", |
904 | 0 | __func__, p); |
905 | 0 | if ((range = ospf_area_range_match( |
906 | 0 | or_area, or_area->ranges, p)) && |
907 | 0 | !ospf_area_is_transit(area)) |
908 | 0 | ospf_abr_update_aggregate(range, or->cost, |
909 | 0 | area); |
910 | 0 | else |
911 | 0 | ospf_abr_announce_network_to_area(p, or->cost, |
912 | 0 | area); |
913 | 0 | } |
914 | 0 | } |
915 | 0 | } |
916 | | |
917 | | static int ospf_abr_should_announce(struct ospf *ospf, struct prefix_ipv4 *p, |
918 | | struct ospf_route * or) |
919 | 0 | { |
920 | 0 | struct ospf_area *area; |
921 | |
|
922 | 0 | area = ospf_area_lookup_by_area_id(ospf, or->u.std.area_id); |
923 | |
|
924 | 0 | assert(area); |
925 | |
|
926 | 0 | if (EXPORT_NAME(area)) { |
927 | 0 | if (EXPORT_LIST(area) == NULL) |
928 | 0 | EXPORT_LIST(area) = |
929 | 0 | access_list_lookup(AFI_IP, EXPORT_NAME(area)); |
930 | |
|
931 | 0 | if (EXPORT_LIST(area)) |
932 | 0 | if (access_list_apply(EXPORT_LIST(area), p) |
933 | 0 | == FILTER_DENY) |
934 | 0 | return 0; |
935 | 0 | } |
936 | | |
937 | 0 | return 1; |
938 | 0 | } |
939 | | |
940 | | static void ospf_abr_process_nssa_translates(struct ospf *ospf) |
941 | 0 | { |
942 | | /* Scan through all NSSA_LSDB records for all areas; |
943 | | |
944 | | If P-bit is on, translate all Type-7's to 5's and aggregate or |
945 | | flood install as approved in Type-5 LSDB with XLATE Flag on |
946 | | later, do same for all aggregates... At end, DISCARD all |
947 | | remaining UNAPPROVED Type-5's (Aggregate is for future ) */ |
948 | 0 | struct listnode *node; |
949 | 0 | struct ospf_area *area; |
950 | 0 | struct route_node *rn; |
951 | 0 | struct ospf_lsa *lsa; |
952 | |
|
953 | 0 | if (IS_DEBUG_OSPF_NSSA) |
954 | 0 | zlog_debug("%s: Start", __func__); |
955 | |
|
956 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
957 | 0 | if (!area->NSSATranslatorState) |
958 | 0 | continue; /* skip if not translator */ |
959 | | |
960 | 0 | if (area->external_routing != OSPF_AREA_NSSA) |
961 | 0 | continue; /* skip if not Nssa Area */ |
962 | | |
963 | 0 | if (IS_DEBUG_OSPF_NSSA) |
964 | 0 | zlog_debug("%s(): looking at area %pI4", __func__, |
965 | 0 | &area->area_id); |
966 | |
|
967 | 0 | LSDB_LOOP (NSSA_LSDB(area), rn, lsa) |
968 | 0 | ospf_abr_translate_nssa(area, lsa); |
969 | 0 | } |
970 | |
|
971 | 0 | if (IS_DEBUG_OSPF_NSSA) |
972 | 0 | zlog_debug("%s: Stop", __func__); |
973 | 0 | } |
974 | | |
975 | | static void ospf_abr_process_network_rt(struct ospf *ospf, |
976 | | struct route_table *rt) |
977 | 0 | { |
978 | 0 | struct ospf_area *area; |
979 | 0 | struct ospf_route * or ; |
980 | 0 | struct route_node *rn; |
981 | |
|
982 | 0 | if (IS_DEBUG_OSPF_EVENT) |
983 | 0 | zlog_debug("%s: Start", __func__); |
984 | |
|
985 | 0 | for (rn = route_top(rt); rn; rn = route_next(rn)) { |
986 | 0 | if ((or = rn->info) == NULL) |
987 | 0 | continue; |
988 | | |
989 | 0 | if (!(area = ospf_area_lookup_by_area_id(ospf, |
990 | 0 | or->u.std.area_id))) { |
991 | 0 | if (IS_DEBUG_OSPF_EVENT) |
992 | 0 | zlog_debug( |
993 | 0 | "%s: area %pI4 no longer exists", __func__, |
994 | 0 | &or->u.std.area_id); |
995 | 0 | continue; |
996 | 0 | } |
997 | | |
998 | 0 | if (IS_DEBUG_OSPF_EVENT) |
999 | 0 | zlog_debug("%s: this is a route to %pFX", __func__, |
1000 | 0 | &rn->p); |
1001 | 0 | if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL) { |
1002 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1003 | 0 | zlog_debug( |
1004 | 0 | "%s: this is an External router, skipping", |
1005 | 0 | __func__); |
1006 | 0 | continue; |
1007 | 0 | } |
1008 | | |
1009 | 0 | if (or->cost >= OSPF_LS_INFINITY) { |
1010 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1011 | 0 | zlog_debug( |
1012 | 0 | "%s: this route's cost is infinity, skipping", |
1013 | 0 | __func__); |
1014 | 0 | continue; |
1015 | 0 | } |
1016 | | |
1017 | 0 | if (or->type == OSPF_DESTINATION_DISCARD) { |
1018 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1019 | 0 | zlog_debug( |
1020 | 0 | "%s: this is a discard entry, skipping", |
1021 | 0 | __func__); |
1022 | 0 | continue; |
1023 | 0 | } |
1024 | | |
1025 | 0 | if ( |
1026 | 0 | or->path_type == OSPF_PATH_INTRA_AREA |
1027 | 0 | && !ospf_abr_should_announce( |
1028 | 0 | ospf, (struct prefix_ipv4 *)&rn->p, |
1029 | 0 | or)) { |
1030 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1031 | 0 | zlog_debug("%s: denied by export-list", |
1032 | 0 | __func__); |
1033 | 0 | continue; |
1034 | 0 | } |
1035 | | |
1036 | 0 | if ( |
1037 | 0 | or->path_type == OSPF_PATH_INTRA_AREA |
1038 | 0 | && !ospf_abr_plist_out_check( |
1039 | 0 | area, or, |
1040 | 0 | (struct prefix_ipv4 *)&rn->p)) { |
1041 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1042 | 0 | zlog_debug("%s: denied by prefix-list", |
1043 | 0 | __func__); |
1044 | 0 | continue; |
1045 | 0 | } |
1046 | | |
1047 | 0 | if ((or->path_type == OSPF_PATH_INTER_AREA) |
1048 | 0 | && !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) { |
1049 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1050 | 0 | zlog_debug( |
1051 | 0 | "%s: this route is not backbone one, skipping", |
1052 | 0 | __func__); |
1053 | 0 | continue; |
1054 | 0 | } |
1055 | | |
1056 | | |
1057 | 0 | if ((ospf->abr_type == OSPF_ABR_CISCO) |
1058 | 0 | || (ospf->abr_type == OSPF_ABR_IBM)) |
1059 | | |
1060 | 0 | if (!ospf_act_bb_connection(ospf) && |
1061 | 0 | or->path_type != OSPF_PATH_INTRA_AREA) { |
1062 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1063 | 0 | zlog_debug( |
1064 | 0 | "%s: ALT ABR: No BB connection, skip not intra-area routes", |
1065 | 0 | __func__); |
1066 | 0 | continue; |
1067 | 0 | } |
1068 | | |
1069 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1070 | 0 | zlog_debug("%s: announcing", __func__); |
1071 | 0 | ospf_abr_announce_network(ospf, (struct prefix_ipv4 *)&rn->p, |
1072 | 0 | or); |
1073 | 0 | } |
1074 | |
|
1075 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1076 | 0 | zlog_debug("%s: Stop", __func__); |
1077 | 0 | } |
1078 | | |
1079 | | static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost, |
1080 | | struct ospf_area *area) |
1081 | 0 | { |
1082 | 0 | struct ospf_lsa *lsa, *old = NULL; |
1083 | 0 | struct summary_lsa *slsa = NULL; |
1084 | |
|
1085 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1086 | 0 | zlog_debug("%s: Start", __func__); |
1087 | |
|
1088 | 0 | old = ospf_lsa_lookup_by_prefix(area->lsdb, OSPF_ASBR_SUMMARY_LSA, p, |
1089 | 0 | area->ospf->router_id); |
1090 | 0 | if (old) { |
1091 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1092 | 0 | zlog_debug("%s: old summary found", __func__); |
1093 | 0 | slsa = (struct summary_lsa *)old->data; |
1094 | |
|
1095 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1096 | 0 | zlog_debug("%s: old metric: %d, new metric: %d", |
1097 | 0 | __func__, GET_METRIC(slsa->metric), cost); |
1098 | 0 | } |
1099 | |
|
1100 | 0 | if (old && (GET_METRIC(slsa->metric) == cost) |
1101 | 0 | && ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) { |
1102 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1103 | 0 | zlog_debug("%s: old summary approved", __func__); |
1104 | 0 | SET_FLAG(old->flags, OSPF_LSA_APPROVED); |
1105 | 0 | } else { |
1106 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1107 | 0 | zlog_debug("%s: 2.2", __func__); |
1108 | |
|
1109 | 0 | if (old) { |
1110 | 0 | set_metric(old, cost); |
1111 | 0 | lsa = ospf_lsa_refresh(area->ospf, old); |
1112 | 0 | } else |
1113 | 0 | lsa = ospf_summary_asbr_lsa_originate(p, cost, area); |
1114 | 0 | if (!lsa) { |
1115 | 0 | flog_warn(EC_OSPF_LSA_MISSING, |
1116 | 0 | "%s: Could not refresh/originate %pFX to %pI4", |
1117 | 0 | __func__, (struct prefix *)p, |
1118 | 0 | &area->area_id); |
1119 | 0 | return; |
1120 | 0 | } |
1121 | | |
1122 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1123 | 0 | zlog_debug("%s: flooding new version of summary", |
1124 | 0 | __func__); |
1125 | | |
1126 | | /* |
1127 | | zlog_info ("ospf_abr_announce_rtr_to_area(): creating new |
1128 | | summary"); |
1129 | | lsa = ospf_summary_asbr_lsa (p, cost, area, old); */ |
1130 | |
|
1131 | 0 | SET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
1132 | | /* ospf_flood_through_area (area, NULL, lsa);*/ |
1133 | 0 | } |
1134 | | |
1135 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1136 | 0 | zlog_debug("%s: Stop", __func__); |
1137 | 0 | } |
1138 | | |
1139 | | |
1140 | | static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p, |
1141 | | struct ospf_route * or) |
1142 | 0 | { |
1143 | 0 | struct listnode *node; |
1144 | 0 | struct ospf_area *area; |
1145 | |
|
1146 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1147 | 0 | zlog_debug("%s: Start", __func__); |
1148 | |
|
1149 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1150 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1151 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
1152 | 0 | &area->area_id); |
1153 | |
|
1154 | 0 | if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id)) |
1155 | 0 | continue; |
1156 | | |
1157 | 0 | if (ospf_abr_nexthops_belong_to_area(or, area)) |
1158 | 0 | continue; |
1159 | | |
1160 | | /* RFC3101: Do not generate ASBR type 4 LSA if NSSA ABR */ |
1161 | 0 | if (or->u.std.external_routing == OSPF_AREA_NSSA) { |
1162 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1163 | 0 | zlog_debug( |
1164 | 0 | "%s: do not generate LSA Type-4 %pI4 from NSSA", |
1165 | 0 | __func__, &p->prefix); |
1166 | 0 | continue; |
1167 | 0 | } |
1168 | | |
1169 | 0 | if (area->external_routing != OSPF_AREA_DEFAULT) { |
1170 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1171 | 0 | zlog_debug( |
1172 | 0 | "%s: area %pI4 doesn't support external routing", |
1173 | 0 | __func__, &area->area_id); |
1174 | 0 | continue; |
1175 | 0 | } |
1176 | | |
1177 | 0 | if (or->path_type == OSPF_PATH_INTER_AREA) { |
1178 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1179 | 0 | zlog_debug( |
1180 | 0 | "%s: this is inter-area route to %pI4", |
1181 | 0 | __func__, &p->prefix); |
1182 | 0 | if (!OSPF_IS_AREA_BACKBONE(area)) |
1183 | 0 | ospf_abr_announce_rtr_to_area(p, or->cost, |
1184 | 0 | area); |
1185 | 0 | } |
1186 | |
|
1187 | 0 | if (or->path_type == OSPF_PATH_INTRA_AREA) { |
1188 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1189 | 0 | zlog_debug( |
1190 | 0 | "%s: this is intra-area route to %pI4", |
1191 | 0 | __func__, &p->prefix); |
1192 | 0 | ospf_abr_announce_rtr_to_area(p, or->cost, area); |
1193 | 0 | } |
1194 | 0 | } |
1195 | |
|
1196 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1197 | 0 | zlog_debug("%s: Stop", __func__); |
1198 | 0 | } |
1199 | | |
1200 | | static void ospf_abr_process_router_rt(struct ospf *ospf, |
1201 | | struct route_table *rt) |
1202 | 0 | { |
1203 | 0 | struct ospf_route * or ; |
1204 | 0 | struct route_node *rn; |
1205 | 0 | struct list *l; |
1206 | |
|
1207 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1208 | 0 | zlog_debug("%s: Start", __func__); |
1209 | |
|
1210 | 0 | for (rn = route_top(rt); rn; rn = route_next(rn)) { |
1211 | 0 | struct listnode *node, *nnode; |
1212 | 0 | char flag = 0; |
1213 | 0 | struct ospf_route *best = NULL; |
1214 | |
|
1215 | 0 | if (rn->info == NULL) |
1216 | 0 | continue; |
1217 | | |
1218 | 0 | l = rn->info; |
1219 | |
|
1220 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1221 | 0 | zlog_debug("%s: this is a route to %pI4", __func__, |
1222 | 0 | &rn->p.u.prefix4); |
1223 | |
|
1224 | 0 | for (ALL_LIST_ELEMENTS(l, node, nnode, or)) { |
1225 | 0 | if (!ospf_area_lookup_by_area_id(ospf, |
1226 | 0 | or->u.std.area_id)) { |
1227 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1228 | 0 | zlog_debug( |
1229 | 0 | "%s: area %pI4 no longer exists", __func__, |
1230 | 0 | &or->u.std.area_id); |
1231 | 0 | continue; |
1232 | 0 | } |
1233 | | |
1234 | | |
1235 | 0 | if (!CHECK_FLAG(or->u.std.flags, ROUTER_LSA_EXTERNAL)) { |
1236 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1237 | 0 | zlog_debug( |
1238 | 0 | "%s: This is not an ASBR, skipping", |
1239 | 0 | __func__); |
1240 | 0 | continue; |
1241 | 0 | } |
1242 | | |
1243 | 0 | if (!flag) { |
1244 | 0 | best = ospf_find_asbr_route( |
1245 | 0 | ospf, rt, (struct prefix_ipv4 *)&rn->p); |
1246 | 0 | flag = 1; |
1247 | 0 | } |
1248 | |
|
1249 | 0 | if (best == NULL) |
1250 | 0 | continue; |
1251 | | |
1252 | 0 | if (or != best) { |
1253 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1254 | 0 | zlog_debug( |
1255 | 0 | "%s: This route is not the best among possible, skipping", |
1256 | 0 | __func__); |
1257 | 0 | continue; |
1258 | 0 | } |
1259 | | |
1260 | 0 | if ( |
1261 | 0 | or->path_type == OSPF_PATH_INTER_AREA |
1262 | 0 | && !OSPF_IS_AREA_ID_BACKBONE( |
1263 | 0 | or->u.std.area_id)) { |
1264 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1265 | 0 | zlog_debug( |
1266 | 0 | "%s: This route is not a backbone one, skipping", |
1267 | 0 | __func__); |
1268 | 0 | continue; |
1269 | 0 | } |
1270 | | |
1271 | 0 | if (or->cost >= OSPF_LS_INFINITY) { |
1272 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1273 | 0 | zlog_debug( |
1274 | 0 | "%s: This route has LS_INFINITY metric, skipping", |
1275 | 0 | __func__); |
1276 | 0 | continue; |
1277 | 0 | } |
1278 | | |
1279 | 0 | if (ospf->abr_type == OSPF_ABR_CISCO |
1280 | 0 | || ospf->abr_type == OSPF_ABR_IBM) |
1281 | 0 | if (!ospf_act_bb_connection(ospf) && |
1282 | 0 | or->path_type != OSPF_PATH_INTRA_AREA) { |
1283 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1284 | 0 | zlog_debug( |
1285 | 0 | "%s: ALT ABR: No BB connection, skip not intra-area routes", |
1286 | 0 | __func__); |
1287 | 0 | continue; |
1288 | 0 | } |
1289 | | |
1290 | 0 | ospf_abr_announce_rtr(ospf, |
1291 | 0 | (struct prefix_ipv4 *)&rn->p, or); |
1292 | 0 | } |
1293 | 0 | } |
1294 | |
|
1295 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1296 | 0 | zlog_debug("%s: Stop", __func__); |
1297 | 0 | } |
1298 | | |
1299 | | static void |
1300 | | ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */ |
1301 | 0 | { |
1302 | 0 | struct ospf_lsa *lsa; |
1303 | 0 | struct route_node *rn; |
1304 | |
|
1305 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1306 | 0 | zlog_debug("%s: Start", __func__); |
1307 | | |
1308 | | /* NSSA Translator is not checked, because it may have gone away, |
1309 | | and we would want to flush any residuals anyway */ |
1310 | |
|
1311 | 0 | LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) |
1312 | 0 | if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) { |
1313 | 0 | UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
1314 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1315 | 0 | zlog_debug("%s: approved unset on link id %pI4", |
1316 | 0 | __func__, &lsa->data->id); |
1317 | 0 | } |
1318 | |
|
1319 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1320 | 0 | zlog_debug("%s: Stop", __func__); |
1321 | 0 | } |
1322 | | |
1323 | | static void ospf_abr_unapprove_summaries(struct ospf *ospf) |
1324 | 0 | { |
1325 | 0 | struct listnode *node; |
1326 | 0 | struct ospf_area *area; |
1327 | 0 | struct route_node *rn; |
1328 | 0 | struct ospf_lsa *lsa; |
1329 | |
|
1330 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1331 | 0 | zlog_debug("%s: Start", __func__); |
1332 | |
|
1333 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1334 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1335 | 0 | zlog_debug("%s: considering area %pI4", __func__, |
1336 | 0 | &area->area_id); |
1337 | 0 | LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa) |
1338 | 0 | if (ospf_lsa_is_self_originated(ospf, lsa)) { |
1339 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1340 | 0 | zlog_debug( |
1341 | 0 | "%s: approved unset on summary link id %pI4", |
1342 | 0 | __func__, &lsa->data->id); |
1343 | 0 | UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
1344 | 0 | } |
1345 | |
|
1346 | 0 | LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa) |
1347 | 0 | if (ospf_lsa_is_self_originated(ospf, lsa)) { |
1348 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1349 | 0 | zlog_debug( |
1350 | 0 | "%s: approved unset on asbr-summary link id %pI4", |
1351 | 0 | __func__, &lsa->data->id); |
1352 | 0 | UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED); |
1353 | 0 | } |
1354 | 0 | } |
1355 | |
|
1356 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1357 | 0 | zlog_debug("%s: Stop", __func__); |
1358 | 0 | } |
1359 | | |
1360 | | static void ospf_abr_prepare_aggregates(struct ospf *ospf, bool nssa) |
1361 | 0 | { |
1362 | 0 | struct listnode *node; |
1363 | 0 | struct route_node *rn; |
1364 | 0 | struct ospf_area_range *range; |
1365 | 0 | struct ospf_area *area; |
1366 | |
|
1367 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1368 | 0 | zlog_debug("%s: Start", __func__); |
1369 | |
|
1370 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1371 | 0 | struct route_table *ranges; |
1372 | |
|
1373 | 0 | if (nssa) |
1374 | 0 | ranges = area->nssa_ranges; |
1375 | 0 | else |
1376 | 0 | ranges = area->ranges; |
1377 | |
|
1378 | 0 | for (rn = route_top(ranges); rn; rn = route_next(rn)) |
1379 | 0 | if ((range = rn->info) != NULL) { |
1380 | 0 | range->cost = 0; |
1381 | 0 | range->specifics = 0; |
1382 | 0 | } |
1383 | 0 | } |
1384 | |
|
1385 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1386 | 0 | zlog_debug("%s: Stop", __func__); |
1387 | 0 | } |
1388 | | |
1389 | | static void ospf_abr_announce_aggregates(struct ospf *ospf) |
1390 | 0 | { |
1391 | 0 | struct ospf_area *area, *ar; |
1392 | 0 | struct ospf_area_range *range; |
1393 | 0 | struct route_node *rn; |
1394 | 0 | struct prefix p; |
1395 | 0 | struct listnode *node, *n; |
1396 | |
|
1397 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1398 | 0 | zlog_debug("%s: Start", __func__); |
1399 | |
|
1400 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1401 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1402 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
1403 | 0 | &area->area_id); |
1404 | |
|
1405 | 0 | for (rn = route_top(area->ranges); rn; rn = route_next(rn)) |
1406 | 0 | if ((range = rn->info)) { |
1407 | 0 | if (!CHECK_FLAG(range->flags, |
1408 | 0 | OSPF_AREA_RANGE_ADVERTISE)) { |
1409 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1410 | 0 | zlog_debug( |
1411 | 0 | "%s: discarding suppress-ranges", |
1412 | 0 | __func__); |
1413 | 0 | continue; |
1414 | 0 | } |
1415 | | |
1416 | 0 | p.family = AF_INET; |
1417 | 0 | p.u.prefix4 = range->addr; |
1418 | 0 | p.prefixlen = range->masklen; |
1419 | |
|
1420 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1421 | 0 | zlog_debug("%s: this is range: %pFX", |
1422 | 0 | __func__, &p); |
1423 | |
|
1424 | 0 | if (CHECK_FLAG(range->flags, |
1425 | 0 | OSPF_AREA_RANGE_SUBSTITUTE)) { |
1426 | 0 | p.family = AF_INET; |
1427 | 0 | p.u.prefix4 = range->subst_addr; |
1428 | 0 | p.prefixlen = range->subst_masklen; |
1429 | 0 | } |
1430 | |
|
1431 | 0 | if (ospf_area_range_active(range)) { |
1432 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1433 | 0 | zlog_debug("%s: active range", |
1434 | 0 | __func__); |
1435 | |
|
1436 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, |
1437 | 0 | n, ar)) { |
1438 | 0 | if (ar == area) |
1439 | 0 | continue; |
1440 | | |
1441 | | /* We do not check nexthops |
1442 | | here, because |
1443 | | intra-area routes can be |
1444 | | associated with |
1445 | | one area only */ |
1446 | | |
1447 | | /* backbone routes are not |
1448 | | summarized |
1449 | | when announced into transit |
1450 | | areas */ |
1451 | | |
1452 | 0 | if (ospf_area_is_transit(ar) |
1453 | 0 | && OSPF_IS_AREA_BACKBONE( |
1454 | 0 | area)) { |
1455 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1456 | 0 | zlog_debug( |
1457 | 0 | "%s: Skipping announcement of BB aggregate into a transit area", |
1458 | 0 | __func__); |
1459 | 0 | continue; |
1460 | 0 | } |
1461 | 0 | ospf_abr_announce_network_to_area( |
1462 | 0 | (struct prefix_ipv4 |
1463 | 0 | *)&p, |
1464 | 0 | range->cost, ar); |
1465 | 0 | } |
1466 | 0 | } |
1467 | 0 | } |
1468 | 0 | } |
1469 | |
|
1470 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1471 | 0 | zlog_debug("%s: Stop", __func__); |
1472 | 0 | } |
1473 | | |
1474 | | static void ospf_abr_send_nssa_aggregates(struct ospf *ospf) |
1475 | 0 | { |
1476 | 0 | struct listnode *node; |
1477 | 0 | struct ospf_area *area; |
1478 | 0 | struct route_node *rn; |
1479 | 0 | struct prefix_ipv4 p; |
1480 | |
|
1481 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1482 | 0 | zlog_debug("%s: Start", __func__); |
1483 | |
|
1484 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1485 | 0 | if (!area->NSSATranslatorState) |
1486 | 0 | continue; |
1487 | | |
1488 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1489 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
1490 | 0 | &area->area_id); |
1491 | |
|
1492 | 0 | for (rn = route_top(area->nssa_ranges); rn; |
1493 | 0 | rn = route_next(rn)) { |
1494 | 0 | struct ospf_area_range *range; |
1495 | |
|
1496 | 0 | range = rn->info; |
1497 | 0 | if (!range) |
1498 | 0 | continue; |
1499 | | |
1500 | 0 | p.family = AF_INET; |
1501 | 0 | p.prefix = range->addr; |
1502 | 0 | p.prefixlen = range->masklen; |
1503 | |
|
1504 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1505 | 0 | zlog_debug("%s: this is range: %pFX", __func__, |
1506 | 0 | &p); |
1507 | |
|
1508 | 0 | if (ospf_area_range_active(range) |
1509 | 0 | && CHECK_FLAG(range->flags, |
1510 | 0 | OSPF_AREA_RANGE_ADVERTISE)) { |
1511 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1512 | 0 | zlog_debug("%s: active range", |
1513 | 0 | __func__); |
1514 | | |
1515 | | /* Fetch LSA-Type-7 from aggregate prefix, and |
1516 | | * then |
1517 | | * translate, Install (as Type-5), Approve, and |
1518 | | * Flood |
1519 | | */ |
1520 | 0 | ospf_abr_translate_nssa_range(ospf, &p, |
1521 | 0 | range->cost); |
1522 | 0 | } |
1523 | 0 | } /* all area ranges*/ |
1524 | 0 | } /* all areas */ |
1525 | |
|
1526 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1527 | 0 | zlog_debug("%s: Stop", __func__); |
1528 | 0 | } |
1529 | | |
1530 | | static void ospf_abr_announce_stub_defaults(struct ospf *ospf) |
1531 | 0 | { |
1532 | 0 | struct listnode *node; |
1533 | 0 | struct ospf_area *area; |
1534 | 0 | struct prefix_ipv4 p; |
1535 | |
|
1536 | 0 | if (!IS_OSPF_ABR(ospf)) |
1537 | 0 | return; |
1538 | | |
1539 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1540 | 0 | zlog_debug("%s: Start", __func__); |
1541 | |
|
1542 | 0 | p.family = AF_INET; |
1543 | 0 | p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; |
1544 | 0 | p.prefixlen = 0; |
1545 | |
|
1546 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1547 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1548 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
1549 | 0 | &area->area_id); |
1550 | |
|
1551 | 0 | if ((area->external_routing != OSPF_AREA_STUB) |
1552 | 0 | && (area->external_routing != OSPF_AREA_NSSA)) |
1553 | 0 | continue; |
1554 | | |
1555 | 0 | if (OSPF_IS_AREA_BACKBONE(area)) |
1556 | 0 | continue; /* Sanity Check */ |
1557 | | |
1558 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1559 | 0 | zlog_debug("%s: announcing 0.0.0.0/0 to area %pI4", |
1560 | 0 | __func__, &area->area_id); |
1561 | 0 | ospf_abr_announce_network_to_area(&p, area->default_cost, area); |
1562 | 0 | } |
1563 | |
|
1564 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1565 | 0 | zlog_debug("%s: Stop", __func__); |
1566 | 0 | } |
1567 | | |
1568 | | /** @brief Function to check and generate indication |
1569 | | * LSA for area on which we received |
1570 | | * indication LSA flush. |
1571 | | * @param Ospf instance. |
1572 | | * @param Area on which indication lsa flush is to be generated. |
1573 | | * @return Void. |
1574 | | */ |
1575 | | void ospf_generate_indication_lsa(struct ospf *ospf, struct ospf_area *area) |
1576 | 0 | { |
1577 | 0 | bool area_fr_not_supp = false; |
1578 | | |
1579 | | /* Check if you have any area which doesn't support |
1580 | | * flood reduction. |
1581 | | */ |
1582 | |
|
1583 | 0 | area_fr_not_supp = ospf_check_fr_enabled_all(ospf) ? false : true; |
1584 | | |
1585 | | /* If any one of the area doestn't support FR, generate |
1586 | | * indication LSA on behalf of that area. |
1587 | | */ |
1588 | |
|
1589 | 0 | if (area_fr_not_supp && !area->fr_info.area_ind_lsa_recvd && |
1590 | 0 | !area->fr_info.indication_lsa_self && |
1591 | 0 | !area->fr_info.area_dc_clear) { |
1592 | |
|
1593 | 0 | struct prefix_ipv4 p; |
1594 | 0 | struct ospf_lsa *new; |
1595 | |
|
1596 | 0 | p.family = AF_INET; |
1597 | 0 | p.prefix = ospf->router_id; |
1598 | 0 | p.prefixlen = IPV4_MAX_BITLEN; |
1599 | |
|
1600 | 0 | new = ospf_summary_asbr_lsa_originate(&p, OSPF_LS_INFINITY, |
1601 | 0 | area); |
1602 | 0 | if (!new) { |
1603 | 0 | zlog_debug("%s: Indication lsa originate failed", |
1604 | 0 | __func__); |
1605 | 0 | return; |
1606 | 0 | } |
1607 | | /* save the indication lsa for that area */ |
1608 | 0 | area->fr_info.indication_lsa_self = new; |
1609 | 0 | } |
1610 | 0 | } |
1611 | | |
1612 | | /** @brief Function to receive and process indication LSA |
1613 | | * flush from area. |
1614 | | * @param lsa being flushed. |
1615 | | * @return Void. |
1616 | | */ |
1617 | | void ospf_recv_indication_lsa_flush(struct ospf_lsa *lsa) |
1618 | 1.08k | { |
1619 | 1.08k | if (!IS_LSA_SELF(lsa) && IS_LSA_MAXAGE(lsa) && |
1620 | 0 | ospf_check_indication_lsa(lsa)) { |
1621 | 0 | lsa->area->fr_info.area_ind_lsa_recvd = false; |
1622 | |
|
1623 | 0 | OSPF_LOG_INFO("%s: Received an ind lsa: %pI4 area %pI4", |
1624 | 0 | __func__, &lsa->data->id, &lsa->area->area_id); |
1625 | |
|
1626 | 0 | if (!IS_OSPF_ABR(lsa->area->ospf)) |
1627 | 0 | return; |
1628 | | |
1629 | | /* If the LSA received is a indication LSA with maxage on |
1630 | | * the network, then check and regenerate indication |
1631 | | * LSA if any of our areas don't support flood reduction. |
1632 | | */ |
1633 | 0 | ospf_generate_indication_lsa(lsa->area->ospf, lsa->area); |
1634 | 0 | } |
1635 | 1.08k | } |
1636 | | |
1637 | | /** @brief Function to generate indication LSAs. |
1638 | | * @param Ospf instance. |
1639 | | * @param Area on behalf of which indication |
1640 | | * LSA is generated LSA. |
1641 | | * @return Void. |
1642 | | */ |
1643 | | void ospf_abr_generate_indication_lsa(struct ospf *ospf, |
1644 | | const struct ospf_area *area) |
1645 | 0 | { |
1646 | 0 | struct ospf_lsa *new; |
1647 | 0 | struct listnode *node; |
1648 | 0 | struct ospf_area *o_area; |
1649 | |
|
1650 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, o_area)) { |
1651 | 0 | if (o_area == area) |
1652 | 0 | continue; |
1653 | | |
1654 | 0 | if (o_area->fr_info.indication_lsa_self || |
1655 | 0 | o_area->fr_info.area_ind_lsa_recvd || |
1656 | 0 | o_area->fr_info.area_dc_clear) { |
1657 | | /* if the area has already received an |
1658 | | * indication LSA or if area already has |
1659 | | * LSAs with DC bit 0 other than |
1660 | | * indication LSA then don't generate |
1661 | | * indication LSA in those areas. |
1662 | | */ |
1663 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, |
1664 | 0 | "Area %pI4 has LSAs with dc bit clear", |
1665 | 0 | &o_area->area_id); |
1666 | 0 | continue; |
1667 | |
|
1668 | 0 | } else { |
1669 | |
|
1670 | 0 | struct prefix_ipv4 p; |
1671 | |
|
1672 | 0 | p.family = AF_INET; |
1673 | 0 | p.prefix = ospf->router_id; |
1674 | 0 | p.prefixlen = IPV4_MAX_BITLEN; |
1675 | |
|
1676 | 0 | new = ospf_summary_asbr_lsa_originate( |
1677 | 0 | &p, OSPF_LS_INFINITY, o_area); |
1678 | 0 | if (!new) { |
1679 | 0 | zlog_debug( |
1680 | 0 | "%s: Indication lsa originate Failed", |
1681 | 0 | __func__); |
1682 | 0 | return; |
1683 | 0 | } |
1684 | | /* save the indication lsa for that area */ |
1685 | 0 | o_area->fr_info.indication_lsa_self = new; |
1686 | 0 | } |
1687 | 0 | } |
1688 | 0 | } |
1689 | | |
1690 | | /** @brief Flush the indication LSA from all the areas |
1691 | | * of ospf instance. |
1692 | | * @param Ospf instance. |
1693 | | * @return Void. |
1694 | | */ |
1695 | | void ospf_flush_indication_lsas(struct ospf *ospf) |
1696 | 0 | { |
1697 | 0 | struct ospf_area *area; |
1698 | 0 | struct listnode *node; |
1699 | |
|
1700 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1701 | 0 | if (area->fr_info.indication_lsa_self) { |
1702 | 0 | OSPF_LOG_INFO( |
1703 | 0 | "Flushing ind lsa: %pI4 area %pI4", |
1704 | 0 | &area->fr_info.indication_lsa_self->data->id, |
1705 | 0 | &area->area_id); |
1706 | 0 | ospf_schedule_lsa_flush_area( |
1707 | 0 | area, area->fr_info.indication_lsa_self); |
1708 | 0 | area->fr_info.indication_lsa_self = NULL; |
1709 | 0 | } |
1710 | 0 | } |
1711 | 0 | } |
1712 | | |
1713 | | /** @brief Check if flood reduction is enabled on |
1714 | | * all the areas. |
1715 | | * @param Ospf instance. |
1716 | | * @return Void. |
1717 | | */ |
1718 | | bool ospf_check_fr_enabled_all(struct ospf *ospf) |
1719 | 0 | { |
1720 | 0 | const struct ospf_area *area; |
1721 | 0 | struct listnode *node; |
1722 | |
|
1723 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) |
1724 | 0 | if (!ospf_check_area_fr_enabled(area)) |
1725 | 0 | return false; |
1726 | | |
1727 | 0 | return true; |
1728 | 0 | } |
1729 | | |
1730 | | /** @brief Abr function to check conditions for generation |
1731 | | * of indication. LSAs/announcing non-DNA routers |
1732 | | * in the area. |
1733 | | * @param thread |
1734 | | * @return 0. |
1735 | | */ |
1736 | | static void ospf_abr_announce_non_dna_routers(struct event *thread) |
1737 | 0 | { |
1738 | 0 | struct ospf_area *area; |
1739 | 0 | struct listnode *node; |
1740 | 0 | struct ospf *ospf = EVENT_ARG(thread); |
1741 | 0 |
|
1742 | 0 | EVENT_OFF(ospf->t_abr_fr); |
1743 | 0 |
|
1744 | 0 | if (!IS_OSPF_ABR(ospf)) |
1745 | 0 | return; |
1746 | 0 |
|
1747 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Start", __func__); |
1748 | 0 |
|
1749 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1750 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, |
1751 | 0 | "%s: Area %pI4 FR enabled: %d", __func__, |
1752 | 0 | &area->area_id, area->fr_info.enabled); |
1753 | 0 | OSPF_LOG_DEBUG( |
1754 | 0 | IS_DEBUG_OSPF_EVENT, |
1755 | 0 | "LSA with DC bit clear: %d Recived indication LSA: %d", |
1756 | 0 | area->fr_info.area_dc_clear, |
1757 | 0 | area->fr_info.area_ind_lsa_recvd); |
1758 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "FR state change: %d", |
1759 | 0 | area->fr_info.state_changed); |
1760 | 0 | if (!OSPF_IS_AREA_BACKBONE(area) && |
1761 | 0 | area->fr_info.area_dc_clear) { |
1762 | 0 | /* rfc4136 rfc1793: Suppose if the abr is connected to |
1763 | 0 | * a regular non-backbone OSPF area, Furthermore if |
1764 | 0 | * the area has LSAs with the DC-bit clear, other |
1765 | 0 | * than indication-LSAs. Then originate indication-LSAs |
1766 | 0 | * into all other directly-connected "regular" areas, |
1767 | 0 | * including the backbone area. |
1768 | 0 | */ |
1769 | 0 | ospf_abr_generate_indication_lsa(ospf, area); |
1770 | 0 | } |
1771 | 0 |
|
1772 | 0 | if (OSPF_IS_AREA_BACKBONE(area) && |
1773 | 0 | (area->fr_info.area_dc_clear || |
1774 | 0 | area->fr_info.area_ind_lsa_recvd)) { |
1775 | 0 | /* rfc4136 rfc1793: Suppose if the abr is connected to |
1776 | 0 | * backbone OSPF area. Furthermore, if backbone has |
1777 | 0 | * LSAs with the DC-bit clear that are either |
1778 | 0 | * a) not indication-LSAs or indication-LSAs or |
1779 | 0 | * b) indication-LSAs that have been originated by |
1780 | 0 | * other routers, |
1781 | 0 | * then originate indication-LSAs into all other |
1782 | 0 | * directly-connected "regular" non-backbone areas. |
1783 | 0 | */ |
1784 | 0 | ospf_abr_generate_indication_lsa(ospf, area); |
1785 | 0 | } |
1786 | 0 |
|
1787 | 0 | if (area->fr_info.enabled && area->fr_info.state_changed && |
1788 | 0 | area->fr_info.indication_lsa_self) { |
1789 | 0 | /* Ospf area flood reduction state changed |
1790 | 0 | * area now supports flood reduction. |
1791 | 0 | * check if all other areas support flood reduction |
1792 | 0 | * if yes then flush indication LSAs generated in |
1793 | 0 | * all the areas. |
1794 | 0 | */ |
1795 | 0 | if (ospf_check_fr_enabled_all(ospf)) |
1796 | 0 | ospf_flush_indication_lsas(ospf); |
1797 | 0 |
|
1798 | 0 | area->fr_info.state_changed = false; |
1799 | 0 | } |
1800 | 0 |
|
1801 | 0 | /* If previously we had generated indication lsa |
1802 | 0 | * but now area has lsas with dc bit set to 0 |
1803 | 0 | * apart from indication lsa, we'll clear indication lsa |
1804 | 0 | */ |
1805 | 0 | if (area->fr_info.area_dc_clear && |
1806 | 0 | area->fr_info.indication_lsa_self) { |
1807 | 0 | ospf_schedule_lsa_flush_area( |
1808 | 0 | area, area->fr_info.indication_lsa_self); |
1809 | 0 | area->fr_info.indication_lsa_self = NULL; |
1810 | 0 | } |
1811 | 0 | } |
1812 | 0 |
|
1813 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, "%s(): Stop", __func__); |
1814 | 0 | } |
1815 | | |
1816 | | static void ospf_abr_nssa_type7_default_create(struct ospf *ospf, |
1817 | | struct ospf_area *area, |
1818 | | struct ospf_lsa *lsa) |
1819 | 0 | { |
1820 | 0 | struct external_info ei; |
1821 | |
|
1822 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1823 | 0 | zlog_debug( |
1824 | 0 | "Announcing Type-7 default route into NSSA area %pI4", |
1825 | 0 | &area->area_id); |
1826 | | |
1827 | | /* Prepare the extrenal_info for aggregator */ |
1828 | 0 | memset(&ei, 0, sizeof(struct external_info)); |
1829 | 0 | ei.p.family = AF_INET; |
1830 | 0 | ei.p.prefixlen = 0; |
1831 | 0 | ei.tag = 0; |
1832 | 0 | ei.type = 0; |
1833 | 0 | ei.instance = ospf->instance; |
1834 | | |
1835 | | /* Compute default route type and metric. */ |
1836 | 0 | if (area->nssa_default_originate.metric_value != -1) |
1837 | 0 | ei.route_map_set.metric = |
1838 | 0 | area->nssa_default_originate.metric_value; |
1839 | 0 | else |
1840 | 0 | ei.route_map_set.metric = DEFAULT_DEFAULT_ALWAYS_METRIC; |
1841 | 0 | if (area->nssa_default_originate.metric_type != -1) |
1842 | 0 | ei.route_map_set.metric_type = |
1843 | 0 | area->nssa_default_originate.metric_type; |
1844 | 0 | else |
1845 | 0 | ei.route_map_set.metric_type = DEFAULT_METRIC_TYPE; |
1846 | |
|
1847 | 0 | if (!lsa) |
1848 | 0 | ospf_nssa_lsa_originate(area, &ei); |
1849 | 0 | else |
1850 | 0 | ospf_nssa_lsa_refresh(area, lsa, &ei); |
1851 | 0 | } |
1852 | | |
1853 | | static void ospf_abr_nssa_type7_default_delete(struct ospf *ospf, |
1854 | | struct ospf_area *area, |
1855 | | struct ospf_lsa *lsa) |
1856 | 0 | { |
1857 | 0 | if (lsa && !CHECK_FLAG(lsa->flags, OSPF_LSA_IN_MAXAGE)) { |
1858 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1859 | 0 | zlog_debug( |
1860 | 0 | "Withdrawing Type-7 default route from area %pI4", |
1861 | 0 | &area->area_id); |
1862 | |
|
1863 | 0 | ospf_ls_retransmit_delete_nbr_area(area, lsa); |
1864 | 0 | ospf_refresher_unregister_lsa(ospf, lsa); |
1865 | 0 | ospf_lsa_flush_area(lsa, area); |
1866 | 0 | } |
1867 | 0 | } |
1868 | | |
1869 | | /* NSSA Type-7 default route. */ |
1870 | | void ospf_abr_nssa_type7_defaults(struct ospf *ospf) |
1871 | 0 | { |
1872 | 0 | struct ospf_area *area; |
1873 | 0 | struct listnode *node; |
1874 | |
|
1875 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1876 | 0 | struct in_addr id = {}; |
1877 | 0 | struct ospf_lsa *lsa; |
1878 | |
|
1879 | 0 | lsa = ospf_lsdb_lookup_by_id(area->lsdb, OSPF_AS_NSSA_LSA, id, |
1880 | 0 | area->ospf->router_id); |
1881 | 0 | if (area->external_routing == OSPF_AREA_NSSA |
1882 | 0 | && area->nssa_default_originate.enabled |
1883 | 0 | && (IS_OSPF_ABR(ospf) |
1884 | 0 | || (IS_OSPF_ASBR(ospf) |
1885 | 0 | && ospf->nssa_default_import_check.status))) |
1886 | 0 | ospf_abr_nssa_type7_default_create(ospf, area, lsa); |
1887 | 0 | else |
1888 | 0 | ospf_abr_nssa_type7_default_delete(ospf, area, lsa); |
1889 | 0 | } |
1890 | 0 | } |
1891 | | |
1892 | | static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf, |
1893 | | struct ospf_lsa *lsa) |
1894 | 0 | { |
1895 | 0 | if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT) |
1896 | 0 | && !CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) { |
1897 | 0 | zlog_info("%s: removing unapproved translates, ID: %pI4", |
1898 | 0 | __func__, &lsa->data->id); |
1899 | | |
1900 | | /* FLUSH THROUGHOUT AS */ |
1901 | 0 | ospf_lsa_flush_as(ospf, lsa); |
1902 | | |
1903 | | /* DISCARD from LSDB */ |
1904 | 0 | } |
1905 | 0 | return 0; |
1906 | 0 | } |
1907 | | |
1908 | | static void ospf_abr_remove_unapproved_translates(struct ospf *ospf) |
1909 | 0 | { |
1910 | 0 | struct route_node *rn; |
1911 | 0 | struct ospf_lsa *lsa; |
1912 | | |
1913 | | /* All AREA PROCESS should have APPROVED necessary LSAs */ |
1914 | | /* Remove any left over and not APPROVED */ |
1915 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1916 | 0 | zlog_debug("%s: Start", __func__); |
1917 | |
|
1918 | 0 | LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) |
1919 | 0 | ospf_abr_remove_unapproved_translates_apply(ospf, lsa); |
1920 | |
|
1921 | 0 | if (IS_DEBUG_OSPF_NSSA) |
1922 | 0 | zlog_debug("%s: Stop", __func__); |
1923 | 0 | } |
1924 | | |
1925 | | static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf) |
1926 | 0 | { |
1927 | 0 | struct listnode *node; |
1928 | 0 | struct ospf_area *area; |
1929 | 0 | struct route_node *rn; |
1930 | 0 | struct ospf_lsa *lsa; |
1931 | |
|
1932 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1933 | 0 | zlog_debug("%s: Start", __func__); |
1934 | |
|
1935 | 0 | for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { |
1936 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1937 | 0 | zlog_debug("%s: looking at area %pI4", __func__, |
1938 | 0 | &area->area_id); |
1939 | |
|
1940 | 0 | LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa) |
1941 | 0 | if (ospf_lsa_is_self_originated(ospf, lsa)) |
1942 | 0 | if (!CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) |
1943 | 0 | ospf_lsa_flush_area(lsa, area); |
1944 | |
|
1945 | 0 | LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa) |
1946 | 0 | if (ospf_lsa_is_self_originated(ospf, lsa) && |
1947 | 0 | !CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED) && |
1948 | | /* Do not remove indication LSAs while |
1949 | | * flushing unapproved summaries. |
1950 | | */ |
1951 | 0 | !ospf_check_indication_lsa(lsa)) |
1952 | 0 | ospf_lsa_flush_area(lsa, area); |
1953 | 0 | } |
1954 | |
|
1955 | 0 | if (IS_DEBUG_OSPF_EVENT) |
1956 | 0 | zlog_debug("%s: Stop", __func__); |
1957 | 0 | } |
1958 | | |
1959 | | static void ospf_abr_manage_discard_routes(struct ospf *ospf, bool nssa) |
1960 | 0 | { |
1961 | 0 | struct listnode *node, *nnode; |
1962 | 0 | struct route_node *rn; |
1963 | 0 | struct ospf_area *area; |
1964 | |
|
1965 | 0 | for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { |
1966 | 0 | struct route_table *ranges; |
1967 | |
|
1968 | 0 | if (nssa) |
1969 | 0 | ranges = area->nssa_ranges; |
1970 | 0 | else |
1971 | 0 | ranges = area->ranges; |
1972 | |
|
1973 | 0 | for (rn = route_top(ranges); rn; rn = route_next(rn)) { |
1974 | 0 | struct ospf_area_range *range; |
1975 | |
|
1976 | 0 | range = rn->info; |
1977 | 0 | if (!range) |
1978 | 0 | continue; |
1979 | | |
1980 | 0 | if (ospf_area_range_active(range) |
1981 | 0 | && CHECK_FLAG(range->flags, |
1982 | 0 | OSPF_AREA_RANGE_ADVERTISE)) |
1983 | 0 | ospf_add_discard_route( |
1984 | 0 | ospf, ospf->new_table, area, |
1985 | 0 | (struct prefix_ipv4 *)&rn->p, nssa); |
1986 | 0 | else |
1987 | 0 | ospf_delete_discard_route( |
1988 | 0 | ospf, ospf->new_table, |
1989 | 0 | (struct prefix_ipv4 *)&rn->p, nssa); |
1990 | 0 | } |
1991 | 0 | } |
1992 | 0 | } |
1993 | | |
1994 | | /* This is the function taking care about ABR NSSA, i.e. NSSA |
1995 | | Translator, -LSA aggregation and flooding. For all NSSAs |
1996 | | |
1997 | | Any SELF-AS-LSA is in the Type-5 LSDB and Type-7 LSDB. These LSA's |
1998 | | are refreshed from the Type-5 LSDB, installed into the Type-7 LSDB |
1999 | | with the P-bit set. |
2000 | | |
2001 | | Any received Type-5s are legal for an ABR, else illegal for IR. |
2002 | | Received Type-7s are installed, by area, with incoming P-bit. They |
2003 | | are flooded; if the Elected NSSA Translator, then P-bit off. |
2004 | | |
2005 | | Additionally, this ABR will place "translated type-7's" into the |
2006 | | Type-5 LSDB in order to keep track of APPROVAL or not. |
2007 | | |
2008 | | It will scan through every area, looking for Type-7 LSAs with P-Bit |
2009 | | SET. The Type-7's are either AS-FLOODED & 5-INSTALLED or |
2010 | | AGGREGATED. Later, the AGGREGATED LSAs are AS-FLOODED & |
2011 | | 5-INSTALLED. |
2012 | | |
2013 | | 5-INSTALLED is into the Type-5 LSDB; Any UNAPPROVED Type-5 LSAs |
2014 | | left over are FLUSHED and DISCARDED. |
2015 | | |
2016 | | For External Calculations, any NSSA areas use the Type-7 AREA-LSDB, |
2017 | | any ABR-non-NSSA areas use the Type-5 GLOBAL-LSDB. */ |
2018 | | |
2019 | | void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */ |
2020 | 0 | { |
2021 | 0 | if (ospf->gr_info.restart_in_progress) |
2022 | 0 | return; |
2023 | | |
2024 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2025 | 0 | zlog_debug("Check for NSSA-ABR Tasks():"); |
2026 | |
|
2027 | 0 | if (!IS_OSPF_ABR(ospf)) |
2028 | 0 | return; |
2029 | | |
2030 | 0 | if (!ospf->anyNSSA) |
2031 | 0 | return; |
2032 | | |
2033 | | /* Each area must confirm TranslatorRole */ |
2034 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2035 | 0 | zlog_debug("%s: Start", __func__); |
2036 | | |
2037 | | /* For all Global Entries flagged "local-translate", unset APPROVED */ |
2038 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2039 | 0 | zlog_debug("%s: unapprove translates", __func__); |
2040 | |
|
2041 | 0 | ospf_abr_unapprove_translates(ospf); |
2042 | | |
2043 | | /* RESET all Ranges in every Area, same as summaries */ |
2044 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2045 | 0 | zlog_debug("%s: NSSA initialize aggregates", __func__); |
2046 | 0 | ospf_abr_prepare_aggregates(ospf, true); |
2047 | | |
2048 | | /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or |
2049 | | * Aggregate as Type-7 |
2050 | | * Install or Approve in Type-5 Global LSDB |
2051 | | */ |
2052 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2053 | 0 | zlog_debug("%s: process translates", __func__); |
2054 | 0 | ospf_abr_process_nssa_translates(ospf); |
2055 | | |
2056 | | /* Translate/Send any "ranged" aggregates, and also 5-Install and |
2057 | | * Approve |
2058 | | * Scan Type-7's for aggregates, translate to Type-5's, |
2059 | | * Install/Flood/Approve |
2060 | | */ |
2061 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2062 | 0 | zlog_debug("%s: send NSSA aggregates", __func__); |
2063 | 0 | ospf_abr_send_nssa_aggregates(ospf); /*TURNED OFF FOR NOW */ |
2064 | | |
2065 | | /* Send any NSSA defaults as Type-5 |
2066 | | *if (IS_DEBUG_OSPF_NSSA) |
2067 | | * zlog_debug ("ospf_abr_nssa_task(): announce nssa defaults"); |
2068 | | *ospf_abr_announce_nssa_defaults (ospf); |
2069 | | * havnt a clue what above is supposed to do. |
2070 | | */ |
2071 | | |
2072 | | /* Flush any unapproved previous translates from Global Data Base */ |
2073 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2074 | 0 | zlog_debug("%s: remove unapproved translates", __func__); |
2075 | 0 | ospf_abr_remove_unapproved_translates(ospf); |
2076 | |
|
2077 | 0 | ospf_abr_manage_discard_routes(ospf, true); |
2078 | |
|
2079 | 0 | if (IS_DEBUG_OSPF_NSSA) |
2080 | 0 | zlog_debug("%s: Stop", __func__); |
2081 | 0 | } |
2082 | | |
2083 | | /* This is the function taking care about ABR stuff, i.e. |
2084 | | summary-LSA origination and flooding. */ |
2085 | | void ospf_abr_task(struct ospf *ospf) |
2086 | 0 | { |
2087 | 0 | if (ospf->gr_info.restart_in_progress) |
2088 | 0 | return; |
2089 | | |
2090 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2091 | 0 | zlog_debug("%s: Start", __func__); |
2092 | |
|
2093 | 0 | if (ospf->new_table == NULL || ospf->new_rtrs == NULL) { |
2094 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2095 | 0 | zlog_debug("%s: Routing tables are not yet ready", |
2096 | 0 | __func__); |
2097 | 0 | return; |
2098 | 0 | } |
2099 | | |
2100 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2101 | 0 | zlog_debug("%s: unapprove summaries", __func__); |
2102 | 0 | ospf_abr_unapprove_summaries(ospf); |
2103 | |
|
2104 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2105 | 0 | zlog_debug("%s: prepare aggregates", __func__); |
2106 | 0 | ospf_abr_prepare_aggregates(ospf, false); |
2107 | |
|
2108 | 0 | if (IS_OSPF_ABR(ospf)) { |
2109 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2110 | 0 | zlog_debug("%s: process network RT", __func__); |
2111 | 0 | ospf_abr_process_network_rt(ospf, ospf->new_table); |
2112 | |
|
2113 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2114 | 0 | zlog_debug("%s: process router RT", __func__); |
2115 | 0 | ospf_abr_process_router_rt(ospf, ospf->new_rtrs); |
2116 | |
|
2117 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2118 | 0 | zlog_debug("%s: announce aggregates", __func__); |
2119 | 0 | ospf_abr_announce_aggregates(ospf); |
2120 | |
|
2121 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2122 | 0 | zlog_debug("%s: announce stub defaults", __func__); |
2123 | 0 | ospf_abr_announce_stub_defaults(ospf); |
2124 | |
|
2125 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2126 | 0 | zlog_debug("%s: announce NSSA Type-7 defaults", |
2127 | 0 | __func__); |
2128 | 0 | ospf_abr_nssa_type7_defaults(ospf); |
2129 | |
|
2130 | 0 | if (ospf->fr_configured) { |
2131 | 0 | OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, |
2132 | 0 | "%s(): announce non-DNArouters", |
2133 | 0 | __func__); |
2134 | | /* |
2135 | | * Schedule indication lsa generation timer, |
2136 | | * giving time for route synchronization in |
2137 | | * all the routers. |
2138 | | */ |
2139 | 0 | event_add_timer(master, |
2140 | 0 | ospf_abr_announce_non_dna_routers, ospf, |
2141 | 0 | OSPF_ABR_DNA_TIMER, &ospf->t_abr_fr); |
2142 | 0 | } |
2143 | 0 | } |
2144 | |
|
2145 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2146 | 0 | zlog_debug("%s: remove unapproved summaries", __func__); |
2147 | 0 | ospf_abr_remove_unapproved_summaries(ospf); |
2148 | |
|
2149 | 0 | ospf_abr_manage_discard_routes(ospf, false); |
2150 | |
|
2151 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2152 | 0 | zlog_debug("%s: Stop", __func__); |
2153 | 0 | } |
2154 | | |
2155 | | static void ospf_abr_task_timer(struct event *thread) |
2156 | 0 | { |
2157 | 0 | struct ospf *ospf = EVENT_ARG(thread); |
2158 | 0 |
|
2159 | 0 | ospf->t_abr_task = 0; |
2160 | 0 |
|
2161 | 0 | if (IS_DEBUG_OSPF_EVENT) |
2162 | 0 | zlog_debug("Running ABR task on timer"); |
2163 | 0 |
|
2164 | 0 | ospf_check_abr_status(ospf); |
2165 | 0 | ospf_abr_nssa_check_status(ospf); |
2166 | 0 |
|
2167 | 0 | ospf_abr_task(ospf); |
2168 | 0 | ospf_abr_nssa_task(ospf); /* if nssa-abr, then scan Type-7 LSDB */ |
2169 | 0 | } |
2170 | | |
2171 | | void ospf_schedule_abr_task(struct ospf *ospf) |
2172 | 63 | { |
2173 | 63 | if (IS_DEBUG_OSPF_EVENT) |
2174 | 0 | zlog_debug("Scheduling ABR task"); |
2175 | | |
2176 | 63 | event_add_timer(master, ospf_abr_task_timer, ospf, OSPF_ABR_TASK_DELAY, |
2177 | 63 | &ospf->t_abr_task); |
2178 | 63 | } |