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