]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_nssa.c
Merge pull request #9028 from mobash-rasool/ospfv3-asbr-summarisation
[mirror_frr.git] / ospf6d / ospf6_nssa.c
1 /*
2 * OSPFv3 Not So Stubby Area implementation.
3 *
4 * Copyright (C) 2021 Kaushik Nath
5 * Copyright (C) 2021 Soman K.S
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <zebra.h>
23 #include "log.h"
24 #include "prefix.h"
25 #include "table.h"
26 #include "vty.h"
27 #include "linklist.h"
28 #include "command.h"
29 #include "thread.h"
30 #include "plist.h"
31 #include "filter.h"
32
33 #include "ospf6_proto.h"
34 #include "ospf6_route.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsdb.h"
38 #include "ospf6_message.h"
39 #include "ospf6_zebra.h"
40
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_neighbor.h"
45
46 #include "ospf6_flood.h"
47 #include "ospf6_intra.h"
48 #include "ospf6_abr.h"
49 #include "ospf6_asbr.h"
50 #include "ospf6d.h"
51 #include "ospf6_nssa.h"
52
53 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
54 unsigned char config_debug_ospf6_nssa = 0;
55 /* Determine whether this router is elected translator or not for area */
56 static int ospf6_abr_nssa_am_elected(struct ospf6_area *oa)
57 {
58 struct ospf6_lsa *lsa;
59 struct ospf6_router_lsa *router_lsa;
60 in_addr_t *best = NULL;
61 uint16_t type;
62
63 type = htons(OSPF6_LSTYPE_ROUTER);
64
65 /* Verify all the router LSA to compare the router ID */
66 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
67
68 router_lsa = (struct ospf6_router_lsa
69 *)((caddr_t)lsa->header
70 + sizeof(struct ospf6_lsa_header));
71
72 /* ignore non-ABR routers */
73 if (!CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B))
74 continue;
75
76 /* Router has Nt flag - always translate */
77 if (CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT)) {
78 if (IS_OSPF6_DEBUG_NSSA)
79 zlog_debug("%s: router %pI4 asserts Nt",
80 __func__, &lsa->header->id);
81 return 1;
82 }
83
84 if (best == NULL)
85 best = &lsa->header->adv_router;
86 else if (IPV4_ADDR_CMP(best, &lsa->header->adv_router) < 0)
87 best = &lsa->header->adv_router;
88 }
89
90 if (best == NULL) {
91 if (IS_OSPF6_DEBUG_NSSA)
92 zlog_debug("%s: best electable ABR not found",
93 __func__);
94 return 0;
95 }
96
97 if (IS_OSPF6_DEBUG_NSSA)
98 zlog_debug("%s: best electable ABR is: %pI4", __func__, best);
99
100 if (IPV4_ADDR_CMP(best, &oa->ospf6->router_id) <= 0) {
101 if (IS_OSPF6_DEBUG_NSSA)
102 zlog_debug("%s: elected ABR is: %pI4", __func__, best);
103 return 1;
104 } else {
105 if (IS_OSPF6_DEBUG_NSSA)
106 zlog_debug("%s: not elected best %pI4, router ID %pI4",
107 __func__, best, &oa->ospf6->router_id);
108 return 0;
109 }
110 }
111
112 /* Flush the translated LSA when translation is disabled */
113 static void ospf6_flush_translated_lsa(struct ospf6_area *area)
114 {
115 uint16_t type;
116 struct ospf6_lsa *type7;
117 struct ospf6_lsa *type5;
118 struct ospf6 *ospf6 = area->ospf6;
119
120 if (IS_OSPF6_DEBUG_NSSA)
121 zlog_debug("%s: start area %s", __func__, area->name);
122
123 type = htons(OSPF6_LSTYPE_TYPE_7);
124 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, type7)) {
125 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
126 type7->external_lsa_id,
127 ospf6->router_id, ospf6->lsdb);
128 if (type5 && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT))
129 ospf6_lsa_premature_aging(type5);
130 }
131 if (IS_OSPF6_DEBUG_NSSA)
132 zlog_debug("%s: finish area %s", __func__, area->name);
133 }
134
135 /* Check NSSA status for all nssa areas*/
136 void ospf6_abr_nssa_check_status(struct ospf6 *ospf6)
137 {
138 struct ospf6_area *area;
139 struct listnode *lnode, *nnode;
140
141 for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, nnode, area)) {
142 uint8_t old_state = area->NSSATranslatorState;
143
144 if (IS_OSPF6_DEBUG_NSSA)
145 zlog_debug("%s: checking area %s flag %x", __func__,
146 area->name, area->flag);
147
148 if (!IS_AREA_NSSA(area))
149 continue;
150
151 if (!CHECK_FLAG(area->ospf6->flag, OSPF6_FLAG_ABR)) {
152 if (IS_OSPF6_DEBUG_NSSA)
153 zlog_debug("%s: not ABR", __func__);
154 area->NSSATranslatorState =
155 OSPF6_NSSA_TRANSLATE_DISABLED;
156 ospf6_flush_translated_lsa(area);
157 } else {
158 /* Router is ABR */
159 if (area->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
160 area->NSSATranslatorState =
161 OSPF6_NSSA_TRANSLATE_ENABLED;
162 else {
163 /* We are a candidate for Translation */
164 if (ospf6_abr_nssa_am_elected(area) > 0) {
165 area->NSSATranslatorState =
166 OSPF6_NSSA_TRANSLATE_ENABLED;
167 if (IS_OSPF6_DEBUG_NSSA)
168 zlog_debug(
169 "%s: elected translator",
170 __func__);
171 } else {
172 area->NSSATranslatorState =
173 OSPF6_NSSA_TRANSLATE_DISABLED;
174 ospf6_flush_translated_lsa(area);
175 if (IS_OSPF6_DEBUG_NSSA)
176 zlog_debug("%s: not elected",
177 __func__);
178 }
179 }
180 }
181
182 /* RFC3101, 3.1:
183 * All NSSA border routers must set the E-bit in the Type-1
184 * router-LSAs of their directly attached non-stub areas, even
185 * when they are not translating.
186 */
187 if (old_state != area->NSSATranslatorState) {
188 if (old_state == OSPF6_NSSA_TRANSLATE_DISABLED)
189 ospf6_asbr_status_update(ospf6,
190 ++ospf6->redist_count);
191 else
192 ospf6_asbr_status_update(ospf6,
193 --ospf6->redist_count);
194 }
195 }
196 }
197
198 /* Mark the summary LSA's as unapproved, when ABR status changes.*/
199 static void ospf6_abr_unapprove_summaries(struct ospf6 *ospf6)
200 {
201 struct listnode *node, *nnode;
202 struct ospf6_area *area;
203 struct ospf6_lsa *lsa;
204 uint16_t type;
205
206 if (IS_OSPF6_DEBUG_ABR)
207 zlog_debug("%s : Start", __func__);
208
209 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
210 if (IS_OSPF6_DEBUG_ABR)
211 zlog_debug("%s : considering area %pI4", __func__,
212 &area->area_id);
213 /* Inter area router LSA */
214 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
215 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
216 lsa)) {
217 if (IS_OSPF6_DEBUG_ABR)
218 zlog_debug(
219 "%s : approved unset on summary link id %pI4",
220 __func__, &lsa->header->id);
221 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
222 }
223 /* Inter area prefix LSA */
224 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
225 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
226 lsa)) {
227 if (IS_OSPF6_DEBUG_ABR)
228 zlog_debug(
229 "%s : approved unset on asbr-summary link id %pI4",
230 __func__, &lsa->header->id);
231 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
232 }
233 }
234
235 if (IS_OSPF6_DEBUG_ABR)
236 zlog_debug("%s : Stop", __func__);
237 }
238
239 /* Re-advertise inter-area router LSA's */
240 void ospf6_asbr_prefix_readvertise(struct ospf6 *ospf6)
241 {
242 struct ospf6_route *brouter;
243 struct listnode *node, *nnode;
244 struct ospf6_area *oa;
245
246 if (IS_OSPF6_DEBUG_ABR)
247 zlog_debug("Re-examining Inter-Router prefixes");
248
249
250 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
251 for (brouter = ospf6_route_head(oa->ospf6->brouter_table);
252 brouter; brouter = ospf6_route_next(brouter))
253 ospf6_abr_originate_summary_to_area(brouter, oa);
254 }
255
256 if (IS_OSPF6_DEBUG_ABR)
257 zlog_debug("Finished re-examining Inter-Router prefixes");
258 }
259
260 /* Advertise prefixes configured using area <area-id> range command */
261 static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
262 {
263 struct ospf6_area *area;
264 struct ospf6_route *range;
265 struct listnode *node, *nnode;
266
267 if (IS_OSPF6_DEBUG_ABR)
268 zlog_debug("ospf6_abr_announce_aggregates(): Start");
269
270 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
271 for (range = ospf6_route_head(area->range_table); range;
272 range = ospf6_route_next(range))
273 ospf6_abr_range_update(range, ospf6);
274 }
275
276 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
277 if (IS_OSPF6_DEBUG_ABR)
278 zlog_debug(
279 "ospf_abr_announce_aggregates(): looking at area %pI4",
280 &area->area_id);
281 }
282
283 if (IS_OSPF6_DEBUG_ABR)
284 zlog_debug("ospf6_abr_announce_aggregates(): Stop");
285 }
286
287 /* Flush the summary LSA's which are not approved.*/
288 void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6)
289 {
290 struct listnode *node, *nnode;
291 struct ospf6_area *area;
292 struct ospf6_lsa *lsa;
293 uint16_t type;
294
295 if (IS_OSPF6_DEBUG_ABR)
296 zlog_debug("%s : Start", __func__);
297
298 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
299 if (IS_OSPF6_DEBUG_ABR)
300 zlog_debug("%s : looking at area %pI4", __func__,
301 &area->area_id);
302
303 /* Inter area router LSA */
304 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
305 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
306 lsa)) {
307 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
308 lsa->header->age = htons(OSPF_LSA_MAXAGE);
309 THREAD_OFF(lsa->refresh);
310 thread_execute(master, ospf6_lsa_expire, lsa,
311 0);
312 }
313 }
314
315 /* Inter area prefix LSA */
316 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
317 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
318 lsa)) {
319 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
320 lsa->header->age = htons(OSPF_LSA_MAXAGE);
321 THREAD_OFF(lsa->refresh);
322 thread_execute(master, ospf6_lsa_expire, lsa,
323 0);
324 }
325 }
326 }
327
328 if (IS_OSPF6_DEBUG_ABR)
329 zlog_debug("%s : Stop", __func__);
330 }
331
332 /*
333 * This is the function taking care about ABR stuff, i.e.
334 * summary-LSA origination and flooding.
335 */
336 static void ospf6_abr_task(struct ospf6 *ospf6)
337 {
338 if (IS_OSPF6_DEBUG_ABR)
339 zlog_debug("%s : Start", __func__);
340
341 if (ospf6->route_table == NULL || ospf6->brouter_table == NULL) {
342 if (IS_OSPF6_DEBUG_ABR)
343 zlog_debug("%s : Routing tables are not yet ready",
344 __func__);
345 return;
346 }
347
348 ospf6_abr_unapprove_summaries(ospf6);
349
350 if (IS_OSPF6_DEBUG_ABR)
351 zlog_debug("%s : prepare aggregates", __func__);
352
353 ospf6_abr_range_reset_cost(ospf6);
354
355 if (IS_OSPF6_ABR(ospf6)) {
356 if (IS_OSPF6_DEBUG_ABR)
357 zlog_debug("%s : process network RT", __func__);
358 ospf6_abr_prefix_resummarize(ospf6);
359
360 if (IS_OSPF6_DEBUG_ABR)
361 zlog_debug("%s : process router RT", __func__);
362 ospf6_asbr_prefix_readvertise(ospf6);
363
364 if (IS_OSPF6_DEBUG_ABR)
365 zlog_debug("%s : announce aggregates", __func__);
366 ospf6_abr_announce_aggregates(ospf6);
367
368 if (IS_OSPF6_DEBUG_ABR)
369 zlog_debug("%s : announce stub defaults", __func__);
370 ospf6_abr_defaults_to_stub(ospf6);
371 }
372
373 if (IS_OSPF6_DEBUG_ABR)
374 zlog_debug("%s : remove unapproved summaries", __func__);
375 ospf6_abr_remove_unapproved_summaries(ospf6);
376
377 if (IS_OSPF6_DEBUG_ABR)
378 zlog_debug("%s : Stop", __func__);
379 }
380
381 /* For NSSA Translations
382 * Mark the translated LSA's as unapproved. */
383 static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
384 {
385 struct ospf6_lsa *lsa;
386 uint16_t type;
387 struct ospf6_area *oa;
388 struct listnode *node;
389
390 if (IS_OSPF6_DEBUG_NSSA)
391 zlog_debug("ospf6_abr_unapprove_translates(): Start");
392
393 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
394 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
395 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
396 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
397 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
398 if (IS_OSPF6_DEBUG_NSSA)
399 zlog_debug(
400 "%s : approved unset on link id %pI4",
401 __func__, &lsa->header->id);
402 }
403 }
404 }
405
406 if (IS_OSPF6_DEBUG_NSSA)
407 zlog_debug("ospf6_abr_unapprove_translates(): Stop");
408 }
409
410 /* Generate the translated external lsa from NSSA lsa */
411 static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
412 struct ospf6_lsa *type7)
413 {
414 char *buffer;
415 struct ospf6_lsa *lsa;
416 struct ospf6_as_external_lsa *ext, *extnew;
417 struct ospf6_lsa_header *lsa_header;
418 caddr_t old_ptr, new_ptr;
419 struct ospf6_as_external_lsa *nssa;
420 struct prefix prefix;
421 struct ospf6_route *match;
422 struct ospf6 *ospf6 = area->ospf6;
423 ptrdiff_t tag_offset = 0;
424 route_tag_t network_order;
425
426 if (IS_OSPF6_DEBUG_NSSA)
427 zlog_debug("%s : Start", __func__);
428
429 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
430 if (IS_OSPF6_DEBUG_NSSA)
431 zlog_debug("%s: Translation disabled for area %s",
432 __func__, area->name);
433 return NULL;
434 }
435
436 buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE);
437 lsa_header = (struct ospf6_lsa_header *)buffer;
438 extnew = (struct ospf6_as_external_lsa
439 *)((caddr_t)lsa_header
440 + sizeof(struct ospf6_lsa_header));
441 ext = (struct ospf6_as_external_lsa
442 *)((caddr_t)(type7->header)
443 + sizeof(struct ospf6_lsa_header));
444 old_ptr =
445 (caddr_t)((caddr_t)ext + sizeof(struct ospf6_as_external_lsa));
446 new_ptr = (caddr_t)((caddr_t)extnew
447 + sizeof(struct ospf6_as_external_lsa));
448
449 memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
450
451 /* find the translated Type-5 for this Type-7 */
452 nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
453 type7->header);
454
455 prefix.family = AF_INET6;
456 prefix.prefixlen = nssa->prefix.prefix_length;
457 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
458
459 /* Find the LSA from the external route */
460 match = ospf6_route_lookup(&prefix, area->route_table);
461 if (match == NULL) {
462 if (IS_OSPF6_DEBUG_NSSA)
463 zlog_debug("%s : no matching route %pFX", __func__,
464 &prefix);
465 return NULL;
466 }
467
468 /* set Prefix */
469 memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
470 ospf6_prefix_apply_mask(&extnew->prefix);
471 new_ptr += OSPF6_PREFIX_SPACE(extnew->prefix.prefix_length);
472
473 tag_offset =
474 sizeof(*ext) + OSPF6_PREFIX_SPACE(ext->prefix.prefix_length);
475
476 /* Forwarding address */
477 if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_F)) {
478 memcpy(new_ptr, (caddr_t)ext + tag_offset,
479 sizeof(struct in6_addr));
480 new_ptr += sizeof(struct in6_addr);
481 tag_offset += sizeof(struct in6_addr);
482 }
483 /* External Route Tag */
484 if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_T)) {
485 memcpy(&network_order, (caddr_t)ext + tag_offset,
486 sizeof(network_order));
487 network_order = htonl(network_order);
488 memcpy(new_ptr, &network_order, sizeof(network_order));
489 new_ptr += sizeof(network_order);
490 }
491
492 /* Fill LSA Header */
493 lsa_header->age = 0;
494 lsa_header->type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
495 lsa_header->id = htonl(ospf6->external_id);
496 ospf6->external_id++;
497 lsa_header->adv_router = ospf6->router_id;
498 lsa_header->seqnum =
499 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
500 lsa_header->adv_router, ospf6->lsdb);
501 lsa_header->length = htons((caddr_t)new_ptr - (caddr_t)lsa_header);
502 type7->external_lsa_id = lsa_header->id;
503
504 /* LSA checksum */
505 ospf6_lsa_checksum(lsa_header);
506
507 /* create LSA */
508 lsa = ospf6_lsa_create(lsa_header);
509
510 SET_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT);
511 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
512
513 /* Originate */
514 ospf6_lsa_originate_process(lsa, ospf6);
515
516 if (IS_OSPF6_DEBUG_NSSA)
517 zlog_debug("%s: Originated type5 LSA id %pI4", __func__,
518 &lsa_header->id);
519 return lsa;
520 }
521
522 /* Delete LSA from retransmission list */
523 static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6 *ospf6,
524 struct ospf6_lsa *lsa)
525 {
526 struct listnode *node, *nnode;
527 struct ospf6_area *area;
528
529 if (IS_OSPF6_DEBUG_NSSA)
530 zlog_debug("%s : start lsa %s", __func__, lsa->name);
531
532 /*The function ospf6_flood_clear_area removes LSA from
533 * retransmit list.
534 */
535 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
536 ospf6_flood_clear_area(lsa, area);
537
538 if (IS_OSPF6_DEBUG_NSSA)
539 zlog_debug("%s : finish lsa %s", __func__, lsa->name);
540 }
541
542 /* Refresh translated AS-external-LSA. */
543 struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
544 struct ospf6_lsa *type7,
545 struct ospf6_lsa *type5)
546 {
547 struct ospf6_lsa *new = NULL;
548 struct ospf6_as_external_lsa *ext_lsa;
549 struct prefix prefix;
550 struct ospf6 *ospf6 = area->ospf6;
551
552 if (IS_OSPF6_DEBUG_NSSA)
553 zlog_debug("%s : start area %s", __func__, area->name);
554
555 /* Sanity checks. */
556 assert(type7);
557
558 /* Find the AS external LSA */
559 if (type5 == NULL) {
560 if (IS_OSPF6_DEBUG_NSSA)
561 zlog_debug(
562 "%s: No translated Type-5 found for Type-7 with Id %pI4",
563 __func__, &type7->header->id);
564
565 /* find the translated Type-5 for this Type-7 */
566 ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
567 type7->header);
568
569 prefix.family = AF_INET6;
570 prefix.prefixlen = ext_lsa->prefix.prefix_length;
571 ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
572 &ext_lsa->prefix);
573
574 /* Find the AS external LSA from Type-7 LSA */
575 if (IS_OSPF6_DEBUG_NSSA)
576 zlog_debug("%s: try to find external LSA id %d",
577 __func__, type7->external_lsa_id);
578 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
579 type7->external_lsa_id,
580 ospf6->router_id, ospf6->lsdb);
581 }
582
583 if (type5) {
584 if (CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
585 /* Delete LSA from neighbor retransmit-list. */
586 ospf6_ls_retransmit_delete_nbr_as(ospf6, type5);
587
588 /* Flush the LSA */
589 ospf6_lsa_premature_aging(type5);
590 } else {
591 if (IS_OSPF6_DEBUG_NSSA)
592 zlog_debug("%s: Invalid translated LSA %s",
593 __func__, type5->name);
594 return NULL;
595 }
596 }
597
598 /* create new translated LSA */
599 if (ospf6_lsa_age_current(type7) != OSPF_LSA_MAXAGE) {
600 if ((new = ospf6_lsa_translated_nssa_new(area, type7))
601 == NULL) {
602 if (IS_OSPF6_DEBUG_NSSA)
603 zlog_debug(
604 "%s: Could not translate Type-7 for %pI4",
605 __func__, &type7->header->id);
606 return NULL;
607 }
608 }
609
610 if (IS_OSPF6_DEBUG_NSSA)
611 zlog_debug("%s: finish", __func__);
612
613 return new;
614 }
615
616 /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
617 struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa,
618 struct ospf6_lsa *type7)
619 {
620 struct ospf6_lsa *new;
621
622 if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7)
623 return NULL;
624
625 if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) {
626 if (IS_OSPF6_DEBUG_NSSA)
627 zlog_debug(
628 "%s : Could not translate Type-7, Id %pI4, to Type-5",
629 __func__, &type7->header->id);
630 return NULL;
631 }
632
633 return new;
634 }
635
636 int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
637 {
638 /* Incoming Type-7 or later aggregated Type-7
639 *
640 * LSA is skipped if P-bit is off.
641 * LSA is aggregated if within range.
642 *
643 * The Type-7 is translated, Installed/Approved as a Type-5 into
644 * global LSDB, then Flooded through AS
645 *
646 * Later, any Unapproved Translated Type-5's are flushed/discarded
647 */
648
649 struct ospf6_lsa *old = NULL, *new = NULL;
650 struct ospf6_as_external_lsa *nssa_lsa;
651 struct prefix prefix;
652 struct ospf6_route *match;
653 struct ospf6 *ospf6;
654
655 ospf6 = area->ospf6;
656 nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
657 lsa->header);
658
659 if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
660 OSPF6_PREFIX_OPTION_P)) {
661 if (IS_OSPF6_DEBUG_NSSA)
662 zlog_debug(
663 "%s : LSA Id %pI4, P-bit off, NO Translation",
664 __func__, &lsa->header->id);
665 return 1;
666 }
667
668 if (IS_OSPF6_DEBUG_NSSA)
669 zlog_debug(
670 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
671 __func__, &lsa->header->id, &lsa->external_lsa_id);
672
673 prefix.family = AF_INET6;
674 prefix.prefixlen = nssa_lsa->prefix.prefix_length;
675 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa_lsa, &nssa_lsa->prefix);
676
677 if (!CHECK_FLAG(nssa_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
678 if (IS_OSPF6_DEBUG_NSSA)
679 zlog_debug(
680 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
681 __func__, &lsa->header->id);
682 return 1;
683 }
684
685 /* Find the existing AS-External LSA for this prefix */
686 match = ospf6_route_lookup(&prefix, ospf6->external_table);
687 if (match) {
688 old = ospf6_lsdb_lookup(OSPF6_LSTYPE_AS_EXTERNAL,
689 match->path.origin.id, ospf6->router_id,
690 ospf6->lsdb);
691 }
692
693 /* Check Type 5 LSA using the matching external ID */
694 if (old == NULL) {
695 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
696 lsa->external_lsa_id, ospf6->router_id,
697 ospf6->lsdb);
698 }
699
700 if (old) {
701 /* Do not continue if type 5 LSA not approved */
702 if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) {
703 if (IS_OSPF6_DEBUG_NSSA)
704 zlog_debug(
705 "%s : LSA Id %pI4 type 5 is not approved",
706 __func__, &old->header->id);
707 return 1;
708 }
709
710 if (IS_OSPF6_DEBUG_NSSA)
711 zlog_debug(
712 "%s : found old translated LSA Id %pI4, refreshing",
713 __func__, &old->header->id);
714
715 /* refresh */
716 new = ospf6_translated_nssa_refresh(area, lsa, old);
717 if (!new) {
718 if (IS_OSPF6_DEBUG_NSSA)
719 zlog_debug(
720 "%s : could not refresh translated LSA Id %pI4",
721 __func__, &old->header->id);
722 }
723 } else {
724 /* no existing external route for this LSA Id
725 * originate translated LSA
726 */
727
728 if (ospf6_translated_nssa_originate(area, lsa) == NULL) {
729 if (IS_OSPF6_DEBUG_NSSA)
730 zlog_debug(
731 "%s : Could not translate Type-7 for %pI4 to Type-5",
732 __func__, &lsa->header->id);
733 return 1;
734 }
735 }
736
737 return 0;
738 }
739
740 static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
741 {
742 /* Scan through all NSSA_LSDB records for all areas;
743 * If P-bit is on, translate all Type-7's to 5's and aggregate or\
744 * flood install as approved in Type-5 LSDB with XLATE Flag on
745 * later, do same for all aggregates... At end, DISCARD all
746 * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
747
748 struct listnode *node;
749 struct ospf6_area *oa;
750 struct ospf6_lsa *lsa;
751 int type;
752
753 if (IS_OSPF6_DEBUG_NSSA)
754 zlog_debug("%s : Start", __func__);
755
756 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
757
758 /* skip if not translator */
759 if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
760 zlog_debug("%s area %pI4 NSSATranslatorState %d",
761 __func__, &oa->area_id,
762 oa->NSSATranslatorState);
763 continue;
764 }
765
766 /* skip if not Nssa Area */
767 if (!IS_AREA_NSSA(oa)) {
768 zlog_debug("%s area %pI4 Flag %x", __func__,
769 &oa->area_id, oa->flag);
770 continue;
771 }
772
773 if (IS_OSPF6_DEBUG_NSSA)
774 zlog_debug("%s : looking at area %pI4", __func__,
775 &oa->area_id);
776
777 type = htons(OSPF6_LSTYPE_TYPE_7);
778 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
779 zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
780 lsa->name, __func__, &lsa->header->id,
781 &lsa->header->adv_router);
782 ospf6_abr_translate_nssa(oa, lsa);
783 }
784 }
785
786 if (IS_OSPF6_DEBUG_NSSA)
787 zlog_debug("%s : Stop", __func__);
788 }
789
790 /* Generate translated type-5 LSA from the configured area ranges*/
791 static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6)
792 {
793 struct listnode *node, *nnode;
794 struct ospf6_area *oa;
795 struct ospf6_route *range;
796 struct ospf6_lsa *lsa;
797
798 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
799 for (range = ospf6_route_head(oa->range_table); range;
800 range = ospf6_route_next(range)) {
801 if (IS_OSPF6_DEBUG_NSSA)
802 zlog_debug(
803 "Translating range %pFX of area %pI4",
804 &range->prefix, &oa->area_id);
805 if (CHECK_FLAG(range->flag,
806 OSPF6_ROUTE_DO_NOT_ADVERTISE))
807 continue;
808
809 /* Find the NSSA LSA from the route */
810 /* Generate and flood external LSA */
811 lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7,
812 range->path.origin.id,
813 ospf6->router_id, oa->lsdb);
814 if (lsa)
815 ospf6_abr_translate_nssa(oa, lsa);
816 }
817 }
818 }
819
820 static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
821 {
822 struct listnode *node;
823 struct ospf6_area *area;
824
825 if (IS_OSPF6_DEBUG_NSSA)
826 zlog_debug("%s : Start", __func__);
827
828 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
829 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
830 continue;
831
832 if (IS_OSPF6_DEBUG_NSSA)
833 zlog_debug("%s : looking at area %pI4", __func__,
834 &area->area_id);
835
836 ospf6_abr_translate_nssa_range(ospf6);
837 }
838
839 if (IS_OSPF6_DEBUG_NSSA)
840 zlog_debug("%s : Stop", __func__);
841 }
842
843 /*Flood max age LSA's for the unapproved LSA's */
844 static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa)
845 {
846 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
847 && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
848 zlog_debug("%s : removing unapproved translates, lsa : %s",
849 __func__, lsa->name);
850
851 /* FLUSH THROUGHOUT AS */
852 ospf6_lsa_premature_aging(lsa);
853 }
854 return 0;
855 }
856
857 static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
858 {
859 struct ospf6_lsa *lsa;
860 uint16_t type;
861
862 /* All AREA PROCESS should have APPROVED necessary LSAs */
863 /* Remove any left over and not APPROVED */
864 if (IS_OSPF6_DEBUG_NSSA)
865 zlog_debug("ospf6_abr_remove_unapproved_translates(): Start");
866
867 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
868 for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa))
869 ospf6_abr_remove_unapproved_translates_apply(lsa);
870
871 if (IS_OSPF6_DEBUG_NSSA)
872 zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
873 }
874
875 static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
876 {
877 /* called only if any_nssa */
878 struct ospf6_route *range;
879 struct ospf6_area *area;
880 struct listnode *node, *nnode;
881
882 if (IS_OSPF6_DEBUG_NSSA)
883 zlog_debug("Check for NSSA-ABR Tasks():");
884
885 if (!IS_OSPF6_ABR(ospf6)) {
886 if (IS_OSPF6_DEBUG_NSSA)
887 zlog_debug("%s Not ABR", __func__);
888 return;
889 }
890
891 if (!ospf6->anyNSSA) {
892 if (IS_OSPF6_DEBUG_NSSA)
893 zlog_debug("%s Not NSSA", __func__);
894 return;
895 }
896
897 /* Each area must confirm TranslatorRole */
898 if (IS_OSPF6_DEBUG_NSSA)
899 zlog_debug("ospf6_abr_nssa_task(): Start");
900
901 /* For all Global Entries flagged "local-translate", unset APPROVED */
902 if (IS_OSPF6_DEBUG_NSSA)
903 zlog_debug("ospf6_abr_nssa_task(): unapprove translates");
904
905 ospf6_abr_unapprove_translates(ospf6);
906
907 /* RESET all Ranges in every Area, same as summaries */
908 if (IS_OSPF6_DEBUG_NSSA)
909 zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates");
910 ospf6_abr_range_reset_cost(ospf6);
911
912 /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
913 * Aggregate as Type-7
914 * Install or Approve in Type-5 Global LSDB
915 */
916 if (IS_OSPF6_DEBUG_NSSA)
917 zlog_debug("ospf6_abr_nssa_task(): process translates");
918 ospf6_abr_process_nssa_translates(ospf6);
919
920 /* Translate/Send any "ranged" aggregates, and also 5-Install and
921 * Approve
922 * Scan Type-7's for aggregates, translate to Type-5's,
923 * Install/Flood/Approve
924 */
925 if (IS_OSPF6_DEBUG_NSSA)
926 zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
927 ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */
928
929 /* Flush any unapproved previous translates from Global Data Base */
930 if (IS_OSPF6_DEBUG_NSSA)
931 zlog_debug(
932 "ospf6_abr_nssa_task(): remove unapproved translates");
933 ospf6_abr_remove_unapproved_translates(ospf6);
934
935 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
936 for (range = ospf6_route_head(area->range_table); range;
937 range = ospf6_route_next(range)) {
938 if (CHECK_FLAG(range->flag,
939 OSPF6_ROUTE_DO_NOT_ADVERTISE))
940 ospf6_zebra_delete_discard(range, ospf6);
941 else
942 ospf6_zebra_add_discard(range, ospf6);
943 }
944 }
945
946 if (IS_OSPF6_DEBUG_NSSA)
947 zlog_debug("ospf6_abr_nssa_task(): Stop");
948 }
949
950 int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
951 int type)
952 {
953 route_map_result_t ret;
954 struct prefix *prefix;
955 struct ospf6_redist *red;
956
957 if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
958 return 0;
959
960 prefix = &route->prefix;
961
962 red = ospf6_redist_lookup(ospf6, type, 0);
963 if (!red)
964 return 0;
965
966 /* Change to new redist structure */
967 if (ROUTEMAP_NAME(red)) {
968 if (ROUTEMAP(red) == NULL)
969 ospf6_asbr_routemap_update(NULL);
970 if (ROUTEMAP(red) == NULL) {
971 zlog_warn(
972 "route-map \"%s\" not found, suppress redistributing",
973 ROUTEMAP_NAME(red));
974 return 0;
975 }
976 }
977
978 /* Change to new redist structure */
979 if (ROUTEMAP(red)) {
980 ret = route_map_apply(ROUTEMAP(red), prefix, route);
981 if (ret == RMAP_DENYMATCH) {
982 if (IS_OSPF6_DEBUG_ASBR)
983 zlog_debug("Denied by route-map \"%s\"",
984 ROUTEMAP_NAME(red));
985 return 0;
986 }
987 }
988
989 return 1;
990 }
991
992 static void ospf6_external_lsa_refresh_type(struct ospf6 *ospf6, uint8_t type,
993 unsigned short instance, int force)
994 {
995 struct ospf6_route *route;
996 struct ospf6_external_info *info;
997 struct ospf6_lsa *lsa;
998
999 if (type == ZEBRA_ROUTE_MAX)
1000 return;
1001
1002 for (route = ospf6_route_head(ospf6->external_table); route;
1003 route = ospf6_route_next(route)) {
1004 info = route->route_option;
1005
1006 /* Find the external LSA in the database */
1007 if (!is_default_prefix(&route->prefix)) {
1008 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1009 htonl(info->id),
1010 ospf6->router_id, ospf6->lsdb);
1011
1012 if (lsa) {
1013 THREAD_OFF(lsa->refresh);
1014
1015 /* LSA is maxage, immediate refresh */
1016 if (OSPF6_LSA_IS_MAXAGE(lsa))
1017 ospf6_flood(NULL, lsa);
1018 else
1019 thread_add_timer(master,
1020 ospf6_lsa_refresh, lsa,
1021 OSPF_LS_REFRESH_TIME,
1022 &lsa->refresh);
1023 } else {
1024 /* LSA not found in the database
1025 * Verify and originate external LSA
1026 */
1027 if (ospf6_redistribute_check(ospf6, route,
1028 type))
1029 ospf6_as_external_lsa_originate(route,
1030 ospf6);
1031 }
1032 }
1033 }
1034 }
1035
1036 /* Refresh default route */
1037 static void ospf6_external_lsa_refresh_default(struct ospf6 *ospf6)
1038 {
1039 struct ospf6_route *route;
1040 struct ospf6_external_info *info;
1041 struct ospf6_lsa *lsa;
1042
1043 for (route = ospf6_route_head(ospf6->external_table); route;
1044 route = ospf6_route_next(route)) {
1045 if (is_default_prefix(&route->prefix)) {
1046 info = route->route_option;
1047 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1048 htonl(info->id),
1049 ospf6->router_id, ospf6->lsdb);
1050
1051 if (lsa) {
1052 if (IS_OSPF6_DEBUG_NSSA)
1053 zlog_debug(
1054 "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
1055 (void *)lsa);
1056 if (OSPF6_LSA_IS_MAXAGE(lsa))
1057 ospf6_flood(NULL, lsa);
1058 else
1059 thread_add_timer(master,
1060 ospf6_lsa_refresh, lsa,
1061 OSPF_LS_REFRESH_TIME,
1062 &lsa->refresh);
1063 } else if (!lsa) {
1064 if (IS_OSPF6_DEBUG_NSSA)
1065 zlog_debug(
1066 "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
1067 ospf6_as_external_lsa_originate(route, ospf6);
1068 }
1069 }
1070 }
1071 }
1072
1073 /* If there's redistribution configured, we need to refresh external
1074 * LSAs in order to install Type-7 and flood to all NSSA Areas
1075 */
1076 void ospf6_asbr_nssa_redist_task(struct ospf6 *ospf6)
1077 {
1078 int type;
1079 struct ospf6_redist *red;
1080
1081 for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
1082 red = ospf6_redist_lookup(ospf6, type, 0);
1083 if (!red)
1084 return;
1085
1086 ospf6_external_lsa_refresh_type(ospf6, type, red->instance,
1087 LSA_REFRESH_IF_CHANGED);
1088 }
1089 ospf6_external_lsa_refresh_default(ospf6);
1090 }
1091
1092 /* This function performs ABR related processing */
1093 static int ospf6_abr_task_timer(struct thread *thread)
1094 {
1095 struct ospf6 *ospf6 = THREAD_ARG(thread);
1096
1097 ospf6->t_abr_task = NULL;
1098
1099 if (IS_OSPF6_DEBUG_ABR)
1100 zlog_debug("Running ABR task on timer");
1101
1102 (void)ospf6_check_and_set_router_abr(ospf6);
1103 ospf6_abr_nssa_check_status(ospf6);
1104 ospf6_abr_task(ospf6);
1105 /* if nssa-abr, then scan Type-7 LSDB */
1106 ospf6_abr_nssa_task(ospf6);
1107 ospf6_asbr_nssa_redist_task(ospf6);
1108
1109 return 0;
1110 }
1111
1112 void ospf6_schedule_abr_task(struct ospf6 *ospf6)
1113 {
1114 if (ospf6->t_abr_task) {
1115 if (IS_OSPF6_DEBUG_ABR)
1116 zlog_debug("ABR task already scheduled");
1117 return;
1118 }
1119
1120 if (IS_OSPF6_DEBUG_ABR)
1121 zlog_debug("Scheduling ABR task");
1122
1123 thread_add_timer(master, ospf6_abr_task_timer, ospf6,
1124 OSPF6_ABR_TASK_DELAY, &ospf6->t_abr_task);
1125 }
1126
1127 /* Flush the NSSA LSAs from the area */
1128 static void ospf6_nssa_flush_area(struct ospf6_area *area)
1129 {
1130 uint16_t type;
1131 struct ospf6_lsa *lsa = NULL, *type5 = NULL;
1132 struct ospf6 *ospf6 = area->ospf6;
1133 const struct route_node *rt = NULL;
1134
1135 if (IS_OSPF6_DEBUG_NSSA)
1136 zlog_debug("%s: area %s", __func__, area->name);
1137
1138 /* Flush the NSSA LSA */
1139 type = htons(OSPF6_LSTYPE_TYPE_7);
1140 rt = ospf6_lsdb_head(area->lsdb_self, 0, type, ospf6->router_id, &lsa);
1141 while (lsa) {
1142 lsa->header->age = htons(OSPF_LSA_MAXAGE);
1143 SET_FLAG(lsa->flag, OSPF6_LSA_FLUSH);
1144 ospf6_flood(NULL, lsa);
1145 /* Flush the translated LSA */
1146 if (ospf6_check_and_set_router_abr(ospf6)) {
1147 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
1148 type5 = ospf6_lsdb_lookup(
1149 htons(type), lsa->external_lsa_id,
1150 ospf6->router_id, ospf6->lsdb);
1151 if (type5
1152 && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
1153 type5->header->age = htons(OSPF_LSA_MAXAGE);
1154 SET_FLAG(type5->flag, OSPF6_LSA_FLUSH);
1155 ospf6_flood(NULL, type5);
1156 }
1157 }
1158 lsa = ospf6_lsdb_next(rt, lsa);
1159 }
1160 }
1161
1162 static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
1163 {
1164 struct ospf6_route *route;
1165 struct route_node *rn = NULL;
1166 struct ospf6_external_aggr_rt *aggr;
1167
1168 /* Loop through the external_table to find the LSAs originated
1169 * without aggregation and originate type-7 LSAs for them.
1170 */
1171 for (route = ospf6_route_head(
1172 area->ospf6->external_table);
1173 route; route = ospf6_route_next(route)) {
1174 /* This means the Type-5 LSA was originated for this route */
1175 if (route->path.origin.id != 0)
1176 ospf6_nssa_lsa_originate(route, area);
1177
1178 }
1179
1180 /* Loop through the aggregation table to originate type-7 LSAs
1181 * for the aggregated type-5 LSAs
1182 */
1183 for (rn = route_top(area->ospf6->rt_aggr_tbl); rn;
1184 rn = route_next(rn)) {
1185 if (!rn->info)
1186 continue;
1187
1188 aggr = rn->info;
1189
1190 if (CHECK_FLAG(aggr->aggrflags,
1191 OSPF6_EXTERNAL_AGGRT_ORIGINATED)) {
1192 if (IS_OSPF6_DEBUG_NSSA)
1193 zlog_debug(
1194 "Originating Type-7 LSAs for area %s",
1195 area->name);
1196
1197 ospf6_nssa_lsa_originate(aggr->route, area);
1198 }
1199 }
1200
1201 }
1202
1203 static void ospf6_area_nssa_update(struct ospf6_area *area)
1204 {
1205 if (IS_AREA_NSSA(area)) {
1206 if (!ospf6_check_and_set_router_abr(area->ospf6))
1207 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
1208 area->ospf6->anyNSSA++;
1209 OSPF6_OPT_SET(area->options, OSPF6_OPT_N);
1210 area->NSSATranslatorRole = OSPF6_NSSA_ROLE_CANDIDATE;
1211 } else if (IS_AREA_ENABLED(area)) {
1212 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
1213 zlog_debug("Normal area for if %s", area->name);
1214 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_N);
1215 if (ospf6_check_and_set_router_abr(area->ospf6))
1216 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
1217 area->ospf6->anyNSSA--;
1218 area->NSSATranslatorState = OSPF6_NSSA_TRANSLATE_DISABLED;
1219 }
1220
1221 /* Refresh router LSA */
1222 if (IS_AREA_NSSA(area)) {
1223 OSPF6_ROUTER_LSA_SCHEDULE(area);
1224
1225 /* Check if router is ABR */
1226 if (ospf6_check_and_set_router_abr(area->ospf6)) {
1227 if (IS_OSPF6_DEBUG_NSSA)
1228 zlog_debug("Router is ABR area %s", area->name);
1229 ospf6_schedule_abr_task(area->ospf6);
1230 } else {
1231 /* Router is not ABR */
1232 if (IS_OSPF6_DEBUG_NSSA)
1233 zlog_debug("NSSA area %s", area->name);
1234
1235 /* Originate NSSA LSA */
1236 ospf6_check_and_originate_type7_lsa(area);
1237 }
1238 } else {
1239 /* Disable NSSA */
1240 if (IS_OSPF6_DEBUG_NSSA)
1241 zlog_debug("Normal area %s", area->name);
1242 ospf6_nssa_flush_area(area);
1243 ospf6_area_disable(area);
1244 ospf6_area_delete(area);
1245 }
1246 }
1247
1248 int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area)
1249 {
1250
1251 if (!IS_AREA_NSSA(area)) {
1252 SET_FLAG(area->flag, OSPF6_AREA_NSSA);
1253 if (IS_OSPF6_DEBUG_NSSA)
1254 zlog_debug("area %s nssa set", area->name);
1255 ospf6_area_nssa_update(area);
1256 }
1257
1258 return 1;
1259 }
1260
1261 int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
1262 {
1263 if (IS_AREA_NSSA(area)) {
1264 UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
1265 if (IS_OSPF6_DEBUG_NSSA)
1266 zlog_debug("area %s nssa reset", area->name);
1267 ospf6_area_nssa_update(area);
1268 }
1269
1270 return 1;
1271 }
1272
1273 /* Find the NSSA forwarding address */
1274 static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
1275 {
1276 struct listnode *node, *nnode;
1277 struct ospf6_interface *oi;
1278
1279 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
1280 if (if_is_operative(oi->interface))
1281 if (oi->area && IS_AREA_NSSA(oi->area))
1282 return ospf6_interface_get_global_address(
1283 oi->interface);
1284 }
1285 return NULL;
1286 }
1287
1288 void ospf6_nssa_lsa_originate(struct ospf6_route *route,
1289 struct ospf6_area *area)
1290 {
1291 char buffer[OSPF6_MAX_LSASIZE];
1292 struct ospf6_lsa_header *lsa_header;
1293 struct ospf6_lsa *lsa;
1294 struct ospf6_external_info *info = route->route_option;
1295 struct in6_addr *fwd_addr;
1296
1297 struct ospf6_as_external_lsa *as_external_lsa;
1298 caddr_t p;
1299
1300 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL))
1301 zlog_debug("Originate NSSA-LSA for %pFX", &route->prefix);
1302
1303 /* prepare buffer */
1304 memset(buffer, 0, sizeof(buffer));
1305 lsa_header = (struct ospf6_lsa_header *)buffer;
1306 as_external_lsa = (struct ospf6_as_external_lsa
1307 *)((caddr_t)lsa_header
1308 + sizeof(struct ospf6_lsa_header));
1309 p = (caddr_t)((caddr_t)as_external_lsa
1310 + sizeof(struct ospf6_as_external_lsa));
1311
1312 /* Fill AS-External-LSA */
1313 /* Metric type */
1314 if (route->path.metric_type == OSPF6_PATH_TYPE_EXTERNAL2)
1315 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1316 else
1317 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1318
1319 /* external route tag */
1320 if (info->tag)
1321 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1322 else
1323 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1324
1325 /* Set metric */
1326 OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
1327
1328 /* prefixlen */
1329 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
1330
1331 /* PrefixOptions */
1332 as_external_lsa->prefix.prefix_options = route->prefix_options;
1333
1334 /* Set the P bit */
1335 as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
1336
1337 /* don't use refer LS-type */
1338 as_external_lsa->prefix.prefix_refer_lstype = htons(0);
1339
1340 /* set Prefix */
1341 memcpy(p, &route->prefix.u.prefix6,
1342 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
1343 ospf6_prefix_apply_mask(&as_external_lsa->prefix);
1344 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
1345
1346 /* Forwarding address */
1347 fwd_addr = ospf6_get_nssa_fwd_addr(area);
1348 if (fwd_addr) {
1349 memcpy(p, fwd_addr, sizeof(struct in6_addr));
1350 p += sizeof(struct in6_addr);
1351 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1352 } else
1353 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1354
1355 /* External Route Tag */
1356 if (CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
1357 route_tag_t network_order = htonl(info->tag);
1358
1359 memcpy(p, &network_order, sizeof(network_order));
1360 p += sizeof(network_order);
1361 }
1362
1363 /* Fill LSA Header */
1364 lsa_header->age = 0;
1365 lsa_header->type = htons(OSPF6_LSTYPE_TYPE_7);
1366 lsa_header->id = route->path.origin.id;
1367 lsa_header->adv_router = area->ospf6->router_id;
1368 lsa_header->seqnum =
1369 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
1370 lsa_header->adv_router, area->lsdb);
1371 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
1372
1373 /* LSA checksum */
1374 ospf6_lsa_checksum(lsa_header);
1375 /* create LSA */
1376 lsa = ospf6_lsa_create(lsa_header);
1377
1378 /* Originate */
1379 ospf6_lsa_originate_area(lsa, area);
1380 }
1381
1382 void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
1383 struct ospf6_lsa *lsa)
1384 {
1385 struct ospf6_lsa *type5 = NULL;
1386 struct ospf6 *ospf6 = area->ospf6;
1387
1388 if (IS_OSPF6_DEBUG_NSSA)
1389 zlog_debug("%s : start", __func__);
1390
1391 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1392 lsa->external_lsa_id, ospf6->router_id,
1393 ospf6->lsdb);
1394
1395 if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) {
1396 if (IS_OSPF6_DEBUG_NSSA)
1397 zlog_debug("%s : Originating type5 LSA", __func__);
1398 ospf6_lsa_translated_nssa_new(area, lsa);
1399 }
1400 }
1401
1402 DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
1403 "debug ospf6 nssa",
1404 DEBUG_STR
1405 OSPF6_STR
1406 "Debug OSPFv3 NSSA function\n")
1407 {
1408 OSPF6_DEBUG_NSSA_ON();
1409 return CMD_SUCCESS;
1410 }
1411
1412 DEFUN(no_debug_ospf6_nssa, no_debug_ospf6_nssa_cmd,
1413 "no debug ospf6 nssa",
1414 NO_STR
1415 DEBUG_STR
1416 OSPF6_STR
1417 "Debug OSPFv3 NSSA function\n")
1418 {
1419 OSPF6_DEBUG_NSSA_OFF();
1420 return CMD_SUCCESS;
1421 }
1422
1423 void config_write_ospf6_debug_nssa(struct vty *vty)
1424 {
1425 if (IS_OSPF6_DEBUG_NSSA)
1426 vty_out(vty, "debug ospf6 nssa\n");
1427 }
1428
1429 void install_element_ospf6_debug_nssa(void)
1430 {
1431 install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
1432 install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
1433 install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
1434 install_element(CONFIG_NODE, &no_debug_ospf6_nssa_cmd);
1435 }