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