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