]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_nssa.c
ospf6d: add "nssa" option to the "debug ospf6 lsa" command
[mirror_frr.git] / ospf6d / ospf6_nssa.c
CommitLineData
ad500b22
K
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
53DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
54unsigned char config_debug_ospf6_nssa = 0;
55/* Determine whether this router is elected translator or not for area */
56static 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 */
113static 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*/
136void 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)) {
edfab98f 142 uint8_t old_state = area->NSSATranslatorState;
ad500b22
K
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 }
edfab98f
IR
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 }
ad500b22 195 }
ad500b22
K
196}
197
198/* Mark the summary LSA's as unapproved, when ABR status changes.*/
199static 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 */
240void 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 */
261static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
262{
263 struct ospf6_area *area;
264 struct ospf6_route *range;
19b8369c 265 struct listnode *node;
ad500b22
K
266
267 if (IS_OSPF6_DEBUG_ABR)
268 zlog_debug("ospf6_abr_announce_aggregates(): Start");
269
ad500b22
K
270 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
271 if (IS_OSPF6_DEBUG_ABR)
272 zlog_debug(
273 "ospf_abr_announce_aggregates(): looking at area %pI4",
274 &area->area_id);
19b8369c
RW
275
276 for (range = ospf6_route_head(area->range_table); range;
277 range = ospf6_route_next(range))
278 ospf6_abr_range_update(range, ospf6);
ad500b22
K
279 }
280
281 if (IS_OSPF6_DEBUG_ABR)
282 zlog_debug("ospf6_abr_announce_aggregates(): Stop");
283}
284
285/* Flush the summary LSA's which are not approved.*/
286void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6)
287{
288 struct listnode *node, *nnode;
289 struct ospf6_area *area;
290 struct ospf6_lsa *lsa;
291 uint16_t type;
292
293 if (IS_OSPF6_DEBUG_ABR)
294 zlog_debug("%s : Start", __func__);
295
296 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
297 if (IS_OSPF6_DEBUG_ABR)
298 zlog_debug("%s : looking at area %pI4", __func__,
299 &area->area_id);
300
301 /* Inter area router LSA */
302 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
303 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
304 lsa)) {
fc3f4adb
DS
305 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
306 ospf6_lsa_premature_aging(lsa);
ad500b22
K
307 }
308
309 /* Inter area prefix LSA */
310 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
311 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
312 lsa)) {
fc3f4adb
DS
313 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
314 ospf6_lsa_premature_aging(lsa);
ad500b22
K
315 }
316 }
317
318 if (IS_OSPF6_DEBUG_ABR)
319 zlog_debug("%s : Stop", __func__);
320}
321
322/*
323 * This is the function taking care about ABR stuff, i.e.
324 * summary-LSA origination and flooding.
325 */
326static void ospf6_abr_task(struct ospf6 *ospf6)
327{
328 if (IS_OSPF6_DEBUG_ABR)
329 zlog_debug("%s : Start", __func__);
330
331 if (ospf6->route_table == NULL || ospf6->brouter_table == NULL) {
332 if (IS_OSPF6_DEBUG_ABR)
333 zlog_debug("%s : Routing tables are not yet ready",
334 __func__);
335 return;
336 }
337
338 ospf6_abr_unapprove_summaries(ospf6);
339
340 if (IS_OSPF6_DEBUG_ABR)
341 zlog_debug("%s : prepare aggregates", __func__);
342
343 ospf6_abr_range_reset_cost(ospf6);
344
345 if (IS_OSPF6_ABR(ospf6)) {
346 if (IS_OSPF6_DEBUG_ABR)
347 zlog_debug("%s : process network RT", __func__);
348 ospf6_abr_prefix_resummarize(ospf6);
349
350 if (IS_OSPF6_DEBUG_ABR)
351 zlog_debug("%s : process router RT", __func__);
352 ospf6_asbr_prefix_readvertise(ospf6);
353
354 if (IS_OSPF6_DEBUG_ABR)
355 zlog_debug("%s : announce aggregates", __func__);
356 ospf6_abr_announce_aggregates(ospf6);
357
358 if (IS_OSPF6_DEBUG_ABR)
359 zlog_debug("%s : announce stub defaults", __func__);
360 ospf6_abr_defaults_to_stub(ospf6);
6735622c
RW
361
362 if (IS_OSPF6_DEBUG_ABR)
363 zlog_debug("%s : announce NSSA Type-7 defaults",
364 __func__);
365 ospf6_abr_nssa_type_7_defaults(ospf6);
ad500b22
K
366 }
367
368 if (IS_OSPF6_DEBUG_ABR)
369 zlog_debug("%s : remove unapproved summaries", __func__);
370 ospf6_abr_remove_unapproved_summaries(ospf6);
371
372 if (IS_OSPF6_DEBUG_ABR)
373 zlog_debug("%s : Stop", __func__);
374}
375
376/* For NSSA Translations
377 * Mark the translated LSA's as unapproved. */
378static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
379{
380 struct ospf6_lsa *lsa;
381 uint16_t type;
382 struct ospf6_area *oa;
383 struct listnode *node;
384
385 if (IS_OSPF6_DEBUG_NSSA)
386 zlog_debug("ospf6_abr_unapprove_translates(): Start");
387
388 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
389 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
390 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
391 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)) {
392 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
393 if (IS_OSPF6_DEBUG_NSSA)
394 zlog_debug(
395 "%s : approved unset on link id %pI4",
396 __func__, &lsa->header->id);
397 }
398 }
399 }
400
401 if (IS_OSPF6_DEBUG_NSSA)
402 zlog_debug("ospf6_abr_unapprove_translates(): Stop");
403}
404
405/* Generate the translated external lsa from NSSA lsa */
406static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
407 struct ospf6_lsa *type7)
408{
409 char *buffer;
410 struct ospf6_lsa *lsa;
411 struct ospf6_as_external_lsa *ext, *extnew;
412 struct ospf6_lsa_header *lsa_header;
413 caddr_t old_ptr, new_ptr;
414 struct ospf6_as_external_lsa *nssa;
415 struct prefix prefix;
416 struct ospf6_route *match;
417 struct ospf6 *ospf6 = area->ospf6;
418 ptrdiff_t tag_offset = 0;
419 route_tag_t network_order;
420
421 if (IS_OSPF6_DEBUG_NSSA)
422 zlog_debug("%s : Start", __func__);
423
424 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
425 if (IS_OSPF6_DEBUG_NSSA)
426 zlog_debug("%s: Translation disabled for area %s",
427 __func__, area->name);
428 return NULL;
429 }
430
431 buffer = XCALLOC(MTYPE_OSPF6_LSA, OSPF6_MAX_LSASIZE);
432 lsa_header = (struct ospf6_lsa_header *)buffer;
433 extnew = (struct ospf6_as_external_lsa
434 *)((caddr_t)lsa_header
435 + sizeof(struct ospf6_lsa_header));
436 ext = (struct ospf6_as_external_lsa
437 *)((caddr_t)(type7->header)
438 + sizeof(struct ospf6_lsa_header));
439 old_ptr =
440 (caddr_t)((caddr_t)ext + sizeof(struct ospf6_as_external_lsa));
441 new_ptr = (caddr_t)((caddr_t)extnew
442 + sizeof(struct ospf6_as_external_lsa));
443
444 memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
445
446 /* find the translated Type-5 for this Type-7 */
447 nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
448 type7->header);
449
450 prefix.family = AF_INET6;
451 prefix.prefixlen = nssa->prefix.prefix_length;
452 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
453
454 /* Find the LSA from the external route */
455 match = ospf6_route_lookup(&prefix, area->route_table);
456 if (match == NULL) {
457 if (IS_OSPF6_DEBUG_NSSA)
458 zlog_debug("%s : no matching route %pFX", __func__,
459 &prefix);
460 return NULL;
461 }
462
463 /* set Prefix */
464 memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
465 ospf6_prefix_apply_mask(&extnew->prefix);
466 new_ptr += OSPF6_PREFIX_SPACE(extnew->prefix.prefix_length);
467
468 tag_offset =
469 sizeof(*ext) + OSPF6_PREFIX_SPACE(ext->prefix.prefix_length);
470
471 /* Forwarding address */
472 if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_F)) {
473 memcpy(new_ptr, (caddr_t)ext + tag_offset,
474 sizeof(struct in6_addr));
475 new_ptr += sizeof(struct in6_addr);
476 tag_offset += sizeof(struct in6_addr);
477 }
478 /* External Route Tag */
479 if (CHECK_FLAG(ext->bits_metric, OSPF6_ASBR_BIT_T)) {
480 memcpy(&network_order, (caddr_t)ext + tag_offset,
481 sizeof(network_order));
482 network_order = htonl(network_order);
483 memcpy(new_ptr, &network_order, sizeof(network_order));
484 new_ptr += sizeof(network_order);
485 }
486
487 /* Fill LSA Header */
488 lsa_header->age = 0;
489 lsa_header->type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
490 lsa_header->id = htonl(ospf6->external_id);
491 ospf6->external_id++;
492 lsa_header->adv_router = ospf6->router_id;
493 lsa_header->seqnum =
494 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
495 lsa_header->adv_router, ospf6->lsdb);
496 lsa_header->length = htons((caddr_t)new_ptr - (caddr_t)lsa_header);
497 type7->external_lsa_id = lsa_header->id;
498
499 /* LSA checksum */
500 ospf6_lsa_checksum(lsa_header);
501
502 /* create LSA */
503 lsa = ospf6_lsa_create(lsa_header);
504
505 SET_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT);
506 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
507
508 /* Originate */
509 ospf6_lsa_originate_process(lsa, ospf6);
510
511 if (IS_OSPF6_DEBUG_NSSA)
512 zlog_debug("%s: Originated type5 LSA id %pI4", __func__,
513 &lsa_header->id);
514 return lsa;
515}
516
517/* Delete LSA from retransmission list */
518static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6 *ospf6,
519 struct ospf6_lsa *lsa)
520{
521 struct listnode *node, *nnode;
522 struct ospf6_area *area;
523
524 if (IS_OSPF6_DEBUG_NSSA)
525 zlog_debug("%s : start lsa %s", __func__, lsa->name);
526
527 /*The function ospf6_flood_clear_area removes LSA from
528 * retransmit list.
529 */
530 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
531 ospf6_flood_clear_area(lsa, area);
532
533 if (IS_OSPF6_DEBUG_NSSA)
534 zlog_debug("%s : finish lsa %s", __func__, lsa->name);
535}
536
537/* Refresh translated AS-external-LSA. */
538struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
539 struct ospf6_lsa *type7,
540 struct ospf6_lsa *type5)
541{
542 struct ospf6_lsa *new = NULL;
543 struct ospf6_as_external_lsa *ext_lsa;
544 struct prefix prefix;
545 struct ospf6 *ospf6 = area->ospf6;
546
547 if (IS_OSPF6_DEBUG_NSSA)
548 zlog_debug("%s : start area %s", __func__, area->name);
549
550 /* Sanity checks. */
551 assert(type7);
552
553 /* Find the AS external LSA */
554 if (type5 == NULL) {
555 if (IS_OSPF6_DEBUG_NSSA)
556 zlog_debug(
557 "%s: No translated Type-5 found for Type-7 with Id %pI4",
558 __func__, &type7->header->id);
559
560 /* find the translated Type-5 for this Type-7 */
561 ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
562 type7->header);
563
564 prefix.family = AF_INET6;
565 prefix.prefixlen = ext_lsa->prefix.prefix_length;
566 ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
567 &ext_lsa->prefix);
568
569 /* Find the AS external LSA from Type-7 LSA */
570 if (IS_OSPF6_DEBUG_NSSA)
571 zlog_debug("%s: try to find external LSA id %d",
572 __func__, type7->external_lsa_id);
573 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
574 type7->external_lsa_id,
575 ospf6->router_id, ospf6->lsdb);
576 }
577
578 if (type5) {
579 if (CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
580 /* Delete LSA from neighbor retransmit-list. */
581 ospf6_ls_retransmit_delete_nbr_as(ospf6, type5);
582
583 /* Flush the LSA */
584 ospf6_lsa_premature_aging(type5);
585 } else {
586 if (IS_OSPF6_DEBUG_NSSA)
587 zlog_debug("%s: Invalid translated LSA %s",
588 __func__, type5->name);
589 return NULL;
590 }
591 }
592
593 /* create new translated LSA */
594 if (ospf6_lsa_age_current(type7) != OSPF_LSA_MAXAGE) {
595 if ((new = ospf6_lsa_translated_nssa_new(area, type7))
596 == NULL) {
597 if (IS_OSPF6_DEBUG_NSSA)
598 zlog_debug(
599 "%s: Could not translate Type-7 for %pI4",
600 __func__, &type7->header->id);
601 return NULL;
602 }
603 }
604
605 if (IS_OSPF6_DEBUG_NSSA)
606 zlog_debug("%s: finish", __func__);
607
608 return new;
609}
610
611/* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
612struct ospf6_lsa *ospf6_translated_nssa_originate(struct ospf6_area *oa,
613 struct ospf6_lsa *type7)
614{
615 struct ospf6_lsa *new;
616
617 if (ntohs(type7->header->type) != OSPF6_LSTYPE_TYPE_7)
618 return NULL;
619
620 if ((new = ospf6_lsa_translated_nssa_new(oa, type7)) == NULL) {
621 if (IS_OSPF6_DEBUG_NSSA)
622 zlog_debug(
623 "%s : Could not translate Type-7, Id %pI4, to Type-5",
624 __func__, &type7->header->id);
625 return NULL;
626 }
627
628 return new;
629}
630
631int ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
632{
633 /* Incoming Type-7 or later aggregated Type-7
634 *
635 * LSA is skipped if P-bit is off.
636 * LSA is aggregated if within range.
637 *
638 * The Type-7 is translated, Installed/Approved as a Type-5 into
639 * global LSDB, then Flooded through AS
640 *
641 * Later, any Unapproved Translated Type-5's are flushed/discarded
642 */
643
644 struct ospf6_lsa *old = NULL, *new = NULL;
645 struct ospf6_as_external_lsa *nssa_lsa;
646 struct prefix prefix;
647 struct ospf6_route *match;
648 struct ospf6 *ospf6;
649
650 ospf6 = area->ospf6;
651 nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
652 lsa->header);
653
654 if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
655 OSPF6_PREFIX_OPTION_P)) {
656 if (IS_OSPF6_DEBUG_NSSA)
657 zlog_debug(
658 "%s : LSA Id %pI4, P-bit off, NO Translation",
659 __func__, &lsa->header->id);
660 return 1;
661 }
662
663 if (IS_OSPF6_DEBUG_NSSA)
664 zlog_debug(
665 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
666 __func__, &lsa->header->id, &lsa->external_lsa_id);
667
668 prefix.family = AF_INET6;
669 prefix.prefixlen = nssa_lsa->prefix.prefix_length;
670 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa_lsa, &nssa_lsa->prefix);
671
672 if (!CHECK_FLAG(nssa_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
673 if (IS_OSPF6_DEBUG_NSSA)
674 zlog_debug(
675 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
676 __func__, &lsa->header->id);
677 return 1;
678 }
679
680 /* Find the existing AS-External LSA for this prefix */
681 match = ospf6_route_lookup(&prefix, ospf6->external_table);
682 if (match) {
683 old = ospf6_lsdb_lookup(OSPF6_LSTYPE_AS_EXTERNAL,
684 match->path.origin.id, ospf6->router_id,
685 ospf6->lsdb);
686 }
687
688 /* Check Type 5 LSA using the matching external ID */
689 if (old == NULL) {
690 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
691 lsa->external_lsa_id, ospf6->router_id,
692 ospf6->lsdb);
693 }
694
695 if (old) {
696 /* Do not continue if type 5 LSA not approved */
697 if (CHECK_FLAG(old->flag, OSPF6_LSA_UNAPPROVED)) {
698 if (IS_OSPF6_DEBUG_NSSA)
699 zlog_debug(
700 "%s : LSA Id %pI4 type 5 is not approved",
701 __func__, &old->header->id);
702 return 1;
703 }
704
705 if (IS_OSPF6_DEBUG_NSSA)
706 zlog_debug(
707 "%s : found old translated LSA Id %pI4, refreshing",
708 __func__, &old->header->id);
709
710 /* refresh */
711 new = ospf6_translated_nssa_refresh(area, lsa, old);
712 if (!new) {
713 if (IS_OSPF6_DEBUG_NSSA)
714 zlog_debug(
715 "%s : could not refresh translated LSA Id %pI4",
716 __func__, &old->header->id);
717 }
718 } else {
719 /* no existing external route for this LSA Id
720 * originate translated LSA
721 */
722
723 if (ospf6_translated_nssa_originate(area, lsa) == NULL) {
724 if (IS_OSPF6_DEBUG_NSSA)
725 zlog_debug(
726 "%s : Could not translate Type-7 for %pI4 to Type-5",
727 __func__, &lsa->header->id);
728 return 1;
729 }
730 }
731
732 return 0;
733}
734
735static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
736{
737 /* Scan through all NSSA_LSDB records for all areas;
738 * If P-bit is on, translate all Type-7's to 5's and aggregate or\
739 * flood install as approved in Type-5 LSDB with XLATE Flag on
740 * later, do same for all aggregates... At end, DISCARD all
741 * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
742
743 struct listnode *node;
744 struct ospf6_area *oa;
745 struct ospf6_lsa *lsa;
746 int type;
747
748 if (IS_OSPF6_DEBUG_NSSA)
749 zlog_debug("%s : Start", __func__);
750
751 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
752
753 /* skip if not translator */
754 if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
755 zlog_debug("%s area %pI4 NSSATranslatorState %d",
756 __func__, &oa->area_id,
757 oa->NSSATranslatorState);
758 continue;
759 }
760
761 /* skip if not Nssa Area */
762 if (!IS_AREA_NSSA(oa)) {
763 zlog_debug("%s area %pI4 Flag %x", __func__,
764 &oa->area_id, oa->flag);
765 continue;
766 }
767
768 if (IS_OSPF6_DEBUG_NSSA)
769 zlog_debug("%s : looking at area %pI4", __func__,
770 &oa->area_id);
771
772 type = htons(OSPF6_LSTYPE_TYPE_7);
773 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
774 zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
775 lsa->name, __func__, &lsa->header->id,
776 &lsa->header->adv_router);
777 ospf6_abr_translate_nssa(oa, lsa);
778 }
779 }
780
781 if (IS_OSPF6_DEBUG_NSSA)
782 zlog_debug("%s : Stop", __func__);
783}
784
785/* Generate translated type-5 LSA from the configured area ranges*/
786static void ospf6_abr_translate_nssa_range(struct ospf6 *ospf6)
787{
788 struct listnode *node, *nnode;
789 struct ospf6_area *oa;
790 struct ospf6_route *range;
791 struct ospf6_lsa *lsa;
792
793 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
794 for (range = ospf6_route_head(oa->range_table); range;
795 range = ospf6_route_next(range)) {
796 if (IS_OSPF6_DEBUG_NSSA)
797 zlog_debug(
798 "Translating range %pFX of area %pI4",
799 &range->prefix, &oa->area_id);
800 if (CHECK_FLAG(range->flag,
801 OSPF6_ROUTE_DO_NOT_ADVERTISE))
802 continue;
803
804 /* Find the NSSA LSA from the route */
805 /* Generate and flood external LSA */
806 lsa = ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7,
807 range->path.origin.id,
808 ospf6->router_id, oa->lsdb);
809 if (lsa)
810 ospf6_abr_translate_nssa(oa, lsa);
811 }
812 }
813}
814
815static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
816{
817 struct listnode *node;
818 struct ospf6_area *area;
819
820 if (IS_OSPF6_DEBUG_NSSA)
821 zlog_debug("%s : Start", __func__);
822
823 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
824 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
825 continue;
826
827 if (IS_OSPF6_DEBUG_NSSA)
828 zlog_debug("%s : looking at area %pI4", __func__,
829 &area->area_id);
830
831 ospf6_abr_translate_nssa_range(ospf6);
832 }
833
834 if (IS_OSPF6_DEBUG_NSSA)
835 zlog_debug("%s : Stop", __func__);
836}
837
838/*Flood max age LSA's for the unapproved LSA's */
839static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa *lsa)
840{
841 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
842 && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
843 zlog_debug("%s : removing unapproved translates, lsa : %s",
844 __func__, lsa->name);
845
846 /* FLUSH THROUGHOUT AS */
847 ospf6_lsa_premature_aging(lsa);
848 }
849 return 0;
850}
851
852static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
853{
854 struct ospf6_lsa *lsa;
855 uint16_t type;
856
857 /* All AREA PROCESS should have APPROVED necessary LSAs */
858 /* Remove any left over and not APPROVED */
859 if (IS_OSPF6_DEBUG_NSSA)
860 zlog_debug("ospf6_abr_remove_unapproved_translates(): Start");
861
862 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
863 for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa))
864 ospf6_abr_remove_unapproved_translates_apply(lsa);
865
866 if (IS_OSPF6_DEBUG_NSSA)
867 zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
868}
869
6735622c
RW
870static void ospf6_abr_nssa_type_7_default_create(struct ospf6 *ospf6,
871 struct ospf6_area *oa)
872{
873 struct ospf6_route *def;
874 int metric;
875 int metric_type;
876
877 if (IS_OSPF6_DEBUG_NSSA)
878 zlog_debug("Announcing Type-7 default route into NSSA area %s",
879 oa->name);
880
881 def = ospf6_route_create(ospf6);
882 def->type = OSPF6_DEST_TYPE_NETWORK;
883 def->prefix.family = AF_INET6;
884 def->prefix.prefixlen = 0;
885 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
886 def->type = OSPF6_DEST_TYPE_NETWORK;
887 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
888 if (CHECK_FLAG(ospf6->flag, OSPF6_FLAG_ABR))
889 def->path.area_id = ospf6->backbone->area_id;
890 else
891 def->path.area_id = oa->area_id;
892
893 /* Compute default route type and metric. */
894 if (oa->nssa_default_originate.metric_value != -1)
895 metric = oa->nssa_default_originate.metric_value;
896 else
897 metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
898 if (oa->nssa_default_originate.metric_type != -1)
899 metric_type = oa->nssa_default_originate.metric_type;
900 else
901 metric_type = DEFAULT_METRIC_TYPE;
902 def->path.metric_type = metric_type;
903 def->path.cost = metric;
904 if (metric_type == 1)
905 def->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
906 else
907 def->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
908
909 ospf6_nssa_lsa_originate(def, oa, false);
910 ospf6_route_delete(def);
911}
912
913static void ospf6_abr_nssa_type_7_default_delete(struct ospf6 *ospf6,
914 struct ospf6_area *oa)
915{
916 struct ospf6_lsa *lsa;
917
918 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), 0,
919 oa->ospf6->router_id, oa->lsdb);
920 if (lsa && !OSPF6_LSA_IS_MAXAGE(lsa)) {
921 if (IS_OSPF6_DEBUG_NSSA)
922 zlog_debug(
923 "Withdrawing Type-7 default route from area %s",
924 oa->name);
925
926 ospf6_lsa_purge(lsa);
927 }
928}
929
930/* NSSA Type-7 default route. */
931void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
932{
933 struct listnode *node;
934 struct ospf6_area *oa;
935
936 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
937 if (IS_AREA_NSSA(oa) && oa->nssa_default_originate.enabled
938 && (IS_OSPF6_ABR(ospf6)
939 || (IS_OSPF6_ASBR(ospf6)
940 && ospf6->nssa_default_import_check.status)))
941 ospf6_abr_nssa_type_7_default_create(ospf6, oa);
942 else
943 ospf6_abr_nssa_type_7_default_delete(ospf6, oa);
944 }
945}
946
ad500b22
K
947static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
948{
949 /* called only if any_nssa */
950 struct ospf6_route *range;
951 struct ospf6_area *area;
952 struct listnode *node, *nnode;
953
954 if (IS_OSPF6_DEBUG_NSSA)
955 zlog_debug("Check for NSSA-ABR Tasks():");
956
957 if (!IS_OSPF6_ABR(ospf6)) {
958 if (IS_OSPF6_DEBUG_NSSA)
959 zlog_debug("%s Not ABR", __func__);
960 return;
961 }
962
963 if (!ospf6->anyNSSA) {
964 if (IS_OSPF6_DEBUG_NSSA)
965 zlog_debug("%s Not NSSA", __func__);
966 return;
967 }
968
969 /* Each area must confirm TranslatorRole */
970 if (IS_OSPF6_DEBUG_NSSA)
971 zlog_debug("ospf6_abr_nssa_task(): Start");
972
973 /* For all Global Entries flagged "local-translate", unset APPROVED */
974 if (IS_OSPF6_DEBUG_NSSA)
975 zlog_debug("ospf6_abr_nssa_task(): unapprove translates");
976
977 ospf6_abr_unapprove_translates(ospf6);
978
979 /* RESET all Ranges in every Area, same as summaries */
980 if (IS_OSPF6_DEBUG_NSSA)
981 zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates");
982 ospf6_abr_range_reset_cost(ospf6);
983
984 /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
985 * Aggregate as Type-7
986 * Install or Approve in Type-5 Global LSDB
987 */
988 if (IS_OSPF6_DEBUG_NSSA)
989 zlog_debug("ospf6_abr_nssa_task(): process translates");
990 ospf6_abr_process_nssa_translates(ospf6);
991
992 /* Translate/Send any "ranged" aggregates, and also 5-Install and
993 * Approve
994 * Scan Type-7's for aggregates, translate to Type-5's,
995 * Install/Flood/Approve
996 */
997 if (IS_OSPF6_DEBUG_NSSA)
998 zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
999 ospf6_abr_send_nssa_aggregates(ospf6); /*TURNED OFF FOR NOW */
1000
1001 /* Flush any unapproved previous translates from Global Data Base */
1002 if (IS_OSPF6_DEBUG_NSSA)
1003 zlog_debug(
1004 "ospf6_abr_nssa_task(): remove unapproved translates");
1005 ospf6_abr_remove_unapproved_translates(ospf6);
1006
1007 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area)) {
1008 for (range = ospf6_route_head(area->range_table); range;
1009 range = ospf6_route_next(range)) {
1010 if (CHECK_FLAG(range->flag,
1011 OSPF6_ROUTE_DO_NOT_ADVERTISE))
1012 ospf6_zebra_delete_discard(range, ospf6);
1013 else
1014 ospf6_zebra_add_discard(range, ospf6);
1015 }
1016 }
1017
1018 if (IS_OSPF6_DEBUG_NSSA)
1019 zlog_debug("ospf6_abr_nssa_task(): Stop");
1020}
1021
1022int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
1023 int type)
1024{
1025 route_map_result_t ret;
1026 struct prefix *prefix;
1027 struct ospf6_redist *red;
1028
1029 if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
1030 return 0;
1031
1032 prefix = &route->prefix;
1033
1034 red = ospf6_redist_lookup(ospf6, type, 0);
1035 if (!red)
1036 return 0;
1037
1038 /* Change to new redist structure */
1039 if (ROUTEMAP_NAME(red)) {
1040 if (ROUTEMAP(red) == NULL)
1041 ospf6_asbr_routemap_update(NULL);
1042 if (ROUTEMAP(red) == NULL) {
1043 zlog_warn(
1044 "route-map \"%s\" not found, suppress redistributing",
1045 ROUTEMAP_NAME(red));
1046 return 0;
1047 }
1048 }
1049
1050 /* Change to new redist structure */
1051 if (ROUTEMAP(red)) {
1052 ret = route_map_apply(ROUTEMAP(red), prefix, route);
1053 if (ret == RMAP_DENYMATCH) {
1054 if (IS_OSPF6_DEBUG_ASBR)
1055 zlog_debug("Denied by route-map \"%s\"",
1056 ROUTEMAP_NAME(red));
1057 return 0;
1058 }
1059 }
1060
1061 return 1;
1062}
1063
ad500b22
K
1064/* This function performs ABR related processing */
1065static int ospf6_abr_task_timer(struct thread *thread)
1066{
1067 struct ospf6 *ospf6 = THREAD_ARG(thread);
1068
1069 ospf6->t_abr_task = NULL;
1070
1071 if (IS_OSPF6_DEBUG_ABR)
1072 zlog_debug("Running ABR task on timer");
1073
95b3f03d 1074 (void)ospf6_check_and_set_router_abr(ospf6);
ad500b22
K
1075 ospf6_abr_nssa_check_status(ospf6);
1076 ospf6_abr_task(ospf6);
1077 /* if nssa-abr, then scan Type-7 LSDB */
1078 ospf6_abr_nssa_task(ospf6);
ad500b22
K
1079
1080 return 0;
1081}
1082
1083void ospf6_schedule_abr_task(struct ospf6 *ospf6)
1084{
1085 if (ospf6->t_abr_task) {
1086 if (IS_OSPF6_DEBUG_ABR)
1087 zlog_debug("ABR task already scheduled");
1088 return;
1089 }
1090
1091 if (IS_OSPF6_DEBUG_ABR)
1092 zlog_debug("Scheduling ABR task");
1093
1094 thread_add_timer(master, ospf6_abr_task_timer, ospf6,
1095 OSPF6_ABR_TASK_DELAY, &ospf6->t_abr_task);
1096}
1097
1098/* Flush the NSSA LSAs from the area */
1099static void ospf6_nssa_flush_area(struct ospf6_area *area)
1100{
1101 uint16_t type;
1102 struct ospf6_lsa *lsa = NULL, *type5 = NULL;
1103 struct ospf6 *ospf6 = area->ospf6;
ad500b22
K
1104
1105 if (IS_OSPF6_DEBUG_NSSA)
1106 zlog_debug("%s: area %s", __func__, area->name);
1107
1108 /* Flush the NSSA LSA */
1109 type = htons(OSPF6_LSTYPE_TYPE_7);
ccfffce4 1110 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
ad500b22
K
1111 lsa->header->age = htons(OSPF_LSA_MAXAGE);
1112 SET_FLAG(lsa->flag, OSPF6_LSA_FLUSH);
1113 ospf6_flood(NULL, lsa);
ccfffce4 1114
ad500b22 1115 /* Flush the translated LSA */
95b3f03d 1116 if (ospf6_check_and_set_router_abr(ospf6)) {
ad500b22
K
1117 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
1118 type5 = ospf6_lsdb_lookup(
1119 htons(type), lsa->external_lsa_id,
1120 ospf6->router_id, ospf6->lsdb);
1121 if (type5
1122 && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
1123 type5->header->age = htons(OSPF_LSA_MAXAGE);
1124 SET_FLAG(type5->flag, OSPF6_LSA_FLUSH);
1125 ospf6_flood(NULL, type5);
1126 }
1127 }
ad500b22
K
1128 }
1129}
1130
c3a70f65 1131static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
ad500b22
K
1132{
1133 struct ospf6_route *route;
c3a70f65 1134 struct route_node *rn = NULL;
c3a70f65
MR
1135 struct ospf6_external_aggr_rt *aggr;
1136
1137 /* Loop through the external_table to find the LSAs originated
1138 * without aggregation and originate type-7 LSAs for them.
1139 */
1140 for (route = ospf6_route_head(
1141 area->ospf6->external_table);
1142 route; route = ospf6_route_next(route)) {
210429c7
RW
1143 struct ospf6_external_info *info = route->route_option;
1144
c3a70f65 1145 /* This means the Type-5 LSA was originated for this route */
210429c7 1146 if (route->path.origin.id != 0 && info->type != DEFAULT_ROUTE)
6735622c 1147 ospf6_nssa_lsa_originate(route, area, true);
c3a70f65 1148 }
ad500b22 1149
c3a70f65
MR
1150 /* Loop through the aggregation table to originate type-7 LSAs
1151 * for the aggregated type-5 LSAs
1152 */
1153 for (rn = route_top(area->ospf6->rt_aggr_tbl); rn;
1154 rn = route_next(rn)) {
1155 if (!rn->info)
1156 continue;
ad500b22 1157
c3a70f65
MR
1158 aggr = rn->info;
1159
1160 if (CHECK_FLAG(aggr->aggrflags,
1161 OSPF6_EXTERNAL_AGGRT_ORIGINATED)) {
c405b00f
MR
1162 if (IS_OSPF6_DEBUG_NSSA)
1163 zlog_debug(
1164 "Originating Type-7 LSAs for area %s",
1165 area->name);
1166
6735622c 1167 ospf6_nssa_lsa_originate(aggr->route, area, true);
c3a70f65
MR
1168 }
1169 }
1170
1171}
1172
0c293b92 1173void ospf6_area_nssa_update(struct ospf6_area *area)
c3a70f65 1174{
ad500b22 1175 if (IS_AREA_NSSA(area)) {
d36a6a19 1176 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
ad500b22
K
1177 area->ospf6->anyNSSA++;
1178 OSPF6_OPT_SET(area->options, OSPF6_OPT_N);
1179 area->NSSATranslatorRole = OSPF6_NSSA_ROLE_CANDIDATE;
1180 } else if (IS_AREA_ENABLED(area)) {
1181 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
1182 zlog_debug("Normal area for if %s", area->name);
1183 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_N);
d36a6a19 1184 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
ad500b22
K
1185 area->ospf6->anyNSSA--;
1186 area->NSSATranslatorState = OSPF6_NSSA_TRANSLATE_DISABLED;
1187 }
1188
1189 /* Refresh router LSA */
1190 if (IS_AREA_NSSA(area)) {
1191 OSPF6_ROUTER_LSA_SCHEDULE(area);
1192
dd551b9d
RW
1193 /* Flush external LSAs. */
1194 ospf6_asbr_remove_externals_from_area(area);
1195
ad500b22 1196 /* Check if router is ABR */
95b3f03d 1197 if (ospf6_check_and_set_router_abr(area->ospf6)) {
ad500b22
K
1198 if (IS_OSPF6_DEBUG_NSSA)
1199 zlog_debug("Router is ABR area %s", area->name);
1200 ospf6_schedule_abr_task(area->ospf6);
1201 } else {
1202 /* Router is not ABR */
1203 if (IS_OSPF6_DEBUG_NSSA)
1204 zlog_debug("NSSA area %s", area->name);
1205
1206 /* Originate NSSA LSA */
c3a70f65 1207 ospf6_check_and_originate_type7_lsa(area);
ad500b22
K
1208 }
1209 } else {
1210 /* Disable NSSA */
1211 if (IS_OSPF6_DEBUG_NSSA)
1212 zlog_debug("Normal area %s", area->name);
1213 ospf6_nssa_flush_area(area);
ad500b22
K
1214 }
1215}
1216
1217int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area)
1218{
1219
1220 if (!IS_AREA_NSSA(area)) {
0c293b92
RW
1221 /* Disable stub first. */
1222 ospf6_area_stub_unset(ospf6, area);
1223
ad500b22
K
1224 SET_FLAG(area->flag, OSPF6_AREA_NSSA);
1225 if (IS_OSPF6_DEBUG_NSSA)
1226 zlog_debug("area %s nssa set", area->name);
1227 ospf6_area_nssa_update(area);
1228 }
1229
1230 return 1;
1231}
1232
1233int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
1234{
1235 if (IS_AREA_NSSA(area)) {
1236 UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
1237 if (IS_OSPF6_DEBUG_NSSA)
1238 zlog_debug("area %s nssa reset", area->name);
1239 ospf6_area_nssa_update(area);
1240 }
1241
1242 return 1;
1243}
1244
1245/* Find the NSSA forwarding address */
1246static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
1247{
1248 struct listnode *node, *nnode;
1249 struct ospf6_interface *oi;
1250
1251 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
1252 if (if_is_operative(oi->interface))
1253 if (oi->area && IS_AREA_NSSA(oi->area))
1254 return ospf6_interface_get_global_address(
1255 oi->interface);
1256 }
1257 return NULL;
1258}
1259
1260void ospf6_nssa_lsa_originate(struct ospf6_route *route,
6735622c 1261 struct ospf6_area *area, bool p_bit)
ad500b22
K
1262{
1263 char buffer[OSPF6_MAX_LSASIZE];
1264 struct ospf6_lsa_header *lsa_header;
1265 struct ospf6_lsa *lsa;
1266 struct ospf6_external_info *info = route->route_option;
1267 struct in6_addr *fwd_addr;
1268
1269 struct ospf6_as_external_lsa *as_external_lsa;
ad500b22
K
1270 caddr_t p;
1271
96cad171
MR
1272 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL))
1273 zlog_debug("Originate NSSA-LSA for %pFX", &route->prefix);
ad500b22
K
1274
1275 /* prepare buffer */
1276 memset(buffer, 0, sizeof(buffer));
1277 lsa_header = (struct ospf6_lsa_header *)buffer;
1278 as_external_lsa = (struct ospf6_as_external_lsa
1279 *)((caddr_t)lsa_header
1280 + sizeof(struct ospf6_lsa_header));
1281 p = (caddr_t)((caddr_t)as_external_lsa
1282 + sizeof(struct ospf6_as_external_lsa));
1283
1284 /* Fill AS-External-LSA */
1285 /* Metric type */
242a9767 1286 if (route->path.metric_type == 2)
ad500b22
K
1287 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1288 else
1289 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1290
1291 /* external route tag */
6735622c 1292 if (info && info->tag)
ad500b22
K
1293 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1294 else
1295 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1296
1297 /* Set metric */
1298 OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
1299
1300 /* prefixlen */
1301 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
1302
1303 /* PrefixOptions */
4699ad72 1304 as_external_lsa->prefix.prefix_options = route->prefix_options;
ad500b22
K
1305
1306 /* Set the P bit */
6735622c
RW
1307 if (p_bit)
1308 as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
ad500b22
K
1309
1310 /* don't use refer LS-type */
1311 as_external_lsa->prefix.prefix_refer_lstype = htons(0);
1312
1313 /* set Prefix */
1314 memcpy(p, &route->prefix.u.prefix6,
1315 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
1316 ospf6_prefix_apply_mask(&as_external_lsa->prefix);
1317 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
1318
1319 /* Forwarding address */
1320 fwd_addr = ospf6_get_nssa_fwd_addr(area);
1321 if (fwd_addr) {
1322 memcpy(p, fwd_addr, sizeof(struct in6_addr));
1323 p += sizeof(struct in6_addr);
1324 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1325 } else
1326 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1327
1328 /* External Route Tag */
6735622c
RW
1329 if (info
1330 && CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
ad500b22
K
1331 route_tag_t network_order = htonl(info->tag);
1332
1333 memcpy(p, &network_order, sizeof(network_order));
1334 p += sizeof(network_order);
1335 }
1336
1337 /* Fill LSA Header */
1338 lsa_header->age = 0;
1339 lsa_header->type = htons(OSPF6_LSTYPE_TYPE_7);
1340 lsa_header->id = route->path.origin.id;
1341 lsa_header->adv_router = area->ospf6->router_id;
1342 lsa_header->seqnum =
1343 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
96cad171 1344 lsa_header->adv_router, area->lsdb);
ad500b22
K
1345 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
1346
1347 /* LSA checksum */
1348 ospf6_lsa_checksum(lsa_header);
1349 /* create LSA */
1350 lsa = ospf6_lsa_create(lsa_header);
1351
1352 /* Originate */
1353 ospf6_lsa_originate_area(lsa, area);
1354}
1355
1356void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
1357 struct ospf6_lsa *lsa)
1358{
1359 struct ospf6_lsa *type5 = NULL;
1360 struct ospf6 *ospf6 = area->ospf6;
1361
1362 if (IS_OSPF6_DEBUG_NSSA)
1363 zlog_debug("%s : start", __func__);
1364
1365 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1366 lsa->external_lsa_id, ospf6->router_id,
1367 ospf6->lsdb);
1368
95b3f03d 1369 if (ospf6_check_and_set_router_abr(ospf6) && (type5 == NULL)) {
ad500b22
K
1370 if (IS_OSPF6_DEBUG_NSSA)
1371 zlog_debug("%s : Originating type5 LSA", __func__);
1372 ospf6_lsa_translated_nssa_new(area, lsa);
1373 }
1374}
1375
1376DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
1377 "debug ospf6 nssa",
1378 DEBUG_STR
1379 OSPF6_STR
1380 "Debug OSPFv3 NSSA function\n")
1381{
1382 OSPF6_DEBUG_NSSA_ON();
1383 return CMD_SUCCESS;
1384}
1385
1386DEFUN(no_debug_ospf6_nssa, no_debug_ospf6_nssa_cmd,
1387 "no debug ospf6 nssa",
1388 NO_STR
1389 DEBUG_STR
1390 OSPF6_STR
1391 "Debug OSPFv3 NSSA function\n")
1392{
1393 OSPF6_DEBUG_NSSA_OFF();
1394 return CMD_SUCCESS;
1395}
1396
1397void config_write_ospf6_debug_nssa(struct vty *vty)
1398{
1399 if (IS_OSPF6_DEBUG_NSSA)
1400 vty_out(vty, "debug ospf6 nssa\n");
1401}
1402
1403void install_element_ospf6_debug_nssa(void)
1404{
1405 install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
1406 install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
1407 install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
1408 install_element(CONFIG_NODE, &no_debug_ospf6_nssa_cmd);
1409}