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