]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_nssa.c
ospf6d: fix typos
[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
416721d9 138/* Check NSSA status for all nssa areas */
ad500b22
K
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)
d8da8a4a 274 zlog_debug("%s: Start", __func__);
ad500b22 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)
d8da8a4a 288 zlog_debug("%s: Stop", __func__);
ad500b22
K
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)
d8da8a4a 390 zlog_debug("%s: Start", __func__);
ad500b22
K
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)
d8da8a4a 404 zlog_debug("%s: Stop", __func__);
ad500b22
K
405}
406
416721d9 407/* Generate the translated external lsa from NSSA lsa */
ad500b22
K
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)
416721d9 539 zlog_debug("%s : finish lsa %s", __func__, lsa->name);
ad500b22
K
540}
541
416721d9 542/* Refresh translated AS-external-LSA. */
ad500b22
K
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 }
607 }
608
609 if (IS_OSPF6_DEBUG_NSSA)
610 zlog_debug("%s: finish", __func__);
611
612 return new;
613}
614
8ee9d58b 615static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *lsa)
ad500b22 616{
416721d9 617 /* Incoming Type-7 or aggregated Type-7
ad500b22
K
618 *
619 * LSA is skipped if P-bit is off.
ad500b22
K
620 *
621 * The Type-7 is translated, Installed/Approved as a Type-5 into
622 * global LSDB, then Flooded through AS
623 *
624 * Later, any Unapproved Translated Type-5's are flushed/discarded
625 */
626
627 struct ospf6_lsa *old = NULL, *new = NULL;
628 struct ospf6_as_external_lsa *nssa_lsa;
629 struct prefix prefix;
630 struct ospf6_route *match;
631 struct ospf6 *ospf6;
632
633 ospf6 = area->ospf6;
634 nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
635 lsa->header);
636
637 if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
638 OSPF6_PREFIX_OPTION_P)) {
639 if (IS_OSPF6_DEBUG_NSSA)
640 zlog_debug(
641 "%s : LSA Id %pI4, P-bit off, NO Translation",
642 __func__, &lsa->header->id);
8ee9d58b 643 return;
ad500b22
K
644 }
645
646 if (IS_OSPF6_DEBUG_NSSA)
647 zlog_debug(
648 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
649 __func__, &lsa->header->id, &lsa->external_lsa_id);
650
651 prefix.family = AF_INET6;
652 prefix.prefixlen = nssa_lsa->prefix.prefix_length;
653 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa_lsa, &nssa_lsa->prefix);
654
655 if (!CHECK_FLAG(nssa_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
656 if (IS_OSPF6_DEBUG_NSSA)
657 zlog_debug(
658 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
659 __func__, &lsa->header->id);
8ee9d58b 660 return;
ad500b22
K
661 }
662
663 /* Find the existing AS-External LSA for this prefix */
664 match = ospf6_route_lookup(&prefix, ospf6->external_table);
665 if (match) {
666 old = ospf6_lsdb_lookup(OSPF6_LSTYPE_AS_EXTERNAL,
667 match->path.origin.id, ospf6->router_id,
668 ospf6->lsdb);
669 }
670
05da1cbf
RW
671 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
672 if (old)
673 ospf6_lsa_premature_aging(old);
674 return;
ad500b22
K
675 }
676
677 if (old) {
ad500b22
K
678 if (IS_OSPF6_DEBUG_NSSA)
679 zlog_debug(
680 "%s : found old translated LSA Id %pI4, refreshing",
681 __func__, &old->header->id);
682
683 /* refresh */
684 new = ospf6_translated_nssa_refresh(area, lsa, old);
685 if (!new) {
686 if (IS_OSPF6_DEBUG_NSSA)
687 zlog_debug(
688 "%s : could not refresh translated LSA Id %pI4",
689 __func__, &old->header->id);
690 }
691 } else {
692 /* no existing external route for this LSA Id
693 * originate translated LSA
694 */
695
8ee9d58b 696 if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) {
ad500b22
K
697 if (IS_OSPF6_DEBUG_NSSA)
698 zlog_debug(
699 "%s : Could not translate Type-7 for %pI4 to Type-5",
700 __func__, &lsa->header->id);
8ee9d58b 701 return;
ad500b22
K
702 }
703 }
ad500b22
K
704}
705
706static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
707{
708 /* Scan through all NSSA_LSDB records for all areas;
416721d9 709 * If P-bit is on, translate all Type-7's to 5's and aggregate or
ad500b22
K
710 * flood install as approved in Type-5 LSDB with XLATE Flag on
711 * later, do same for all aggregates... At end, DISCARD all
712 * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
713
714 struct listnode *node;
715 struct ospf6_area *oa;
716 struct ospf6_lsa *lsa;
717 int type;
718
719 if (IS_OSPF6_DEBUG_NSSA)
720 zlog_debug("%s : Start", __func__);
721
722 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
8ee9d58b
RW
723 if (!IS_AREA_NSSA(oa))
724 continue;
ad500b22
K
725
726 /* skip if not translator */
727 if (oa->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED) {
728 zlog_debug("%s area %pI4 NSSATranslatorState %d",
729 __func__, &oa->area_id,
730 oa->NSSATranslatorState);
731 continue;
732 }
733
ad500b22
K
734 if (IS_OSPF6_DEBUG_NSSA)
735 zlog_debug("%s : looking at area %pI4", __func__,
736 &oa->area_id);
737
738 type = htons(OSPF6_LSTYPE_TYPE_7);
739 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
740 zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
416721d9 741 __func__, lsa->name, &lsa->header->id,
ad500b22
K
742 &lsa->header->adv_router);
743 ospf6_abr_translate_nssa(oa, lsa);
744 }
745 }
746
747 if (IS_OSPF6_DEBUG_NSSA)
748 zlog_debug("%s : Stop", __func__);
749}
750
ad500b22
K
751static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
752{
753 struct listnode *node;
754 struct ospf6_area *area;
3c77bc80 755 struct ospf6_route *range;
ad500b22
K
756
757 if (IS_OSPF6_DEBUG_NSSA)
3c77bc80 758 zlog_debug("%s: Start", __func__);
ad500b22
K
759
760 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
761 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
762 continue;
763
764 if (IS_OSPF6_DEBUG_NSSA)
3c77bc80 765 zlog_debug("%s: looking at area %pI4", __func__,
ad500b22
K
766 &area->area_id);
767
3c77bc80
RW
768 for (range = ospf6_route_head(area->nssa_range_table); range;
769 range = ospf6_route_next(range))
770 ospf6_abr_range_update(range, ospf6);
ad500b22
K
771 }
772
773 if (IS_OSPF6_DEBUG_NSSA)
3c77bc80 774 zlog_debug("%s: Stop", __func__);
ad500b22
K
775}
776
777static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
778{
779 struct ospf6_lsa *lsa;
780 uint16_t type;
781
782 /* All AREA PROCESS should have APPROVED necessary LSAs */
783 /* Remove any left over and not APPROVED */
784 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 785 zlog_debug("%s: Start", __func__);
ad500b22
K
786
787 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
8ee9d58b
RW
788 for (ALL_LSDB_TYPED(ospf6->lsdb, type, lsa)) {
789 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT)
790 && CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED)) {
791 zlog_debug(
792 "%s : removing unapproved translates, lsa : %s",
793 __func__, lsa->name);
794
795 ospf6_lsa_premature_aging(lsa);
796 }
797 }
ad500b22
K
798
799 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 800 zlog_debug("%s: Stop", __func__);
ad500b22
K
801}
802
6735622c
RW
803static void ospf6_abr_nssa_type_7_default_create(struct ospf6 *ospf6,
804 struct ospf6_area *oa)
805{
806 struct ospf6_route *def;
807 int metric;
808 int metric_type;
809
810 if (IS_OSPF6_DEBUG_NSSA)
811 zlog_debug("Announcing Type-7 default route into NSSA area %s",
812 oa->name);
813
814 def = ospf6_route_create(ospf6);
815 def->type = OSPF6_DEST_TYPE_NETWORK;
816 def->prefix.family = AF_INET6;
817 def->prefix.prefixlen = 0;
818 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
819 def->type = OSPF6_DEST_TYPE_NETWORK;
820 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
821 if (CHECK_FLAG(ospf6->flag, OSPF6_FLAG_ABR))
822 def->path.area_id = ospf6->backbone->area_id;
823 else
824 def->path.area_id = oa->area_id;
825
826 /* Compute default route type and metric. */
827 if (oa->nssa_default_originate.metric_value != -1)
828 metric = oa->nssa_default_originate.metric_value;
829 else
830 metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
831 if (oa->nssa_default_originate.metric_type != -1)
832 metric_type = oa->nssa_default_originate.metric_type;
833 else
834 metric_type = DEFAULT_METRIC_TYPE;
835 def->path.metric_type = metric_type;
836 def->path.cost = metric;
837 if (metric_type == 1)
838 def->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
839 else
840 def->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
841
842 ospf6_nssa_lsa_originate(def, oa, false);
843 ospf6_route_delete(def);
844}
845
846static void ospf6_abr_nssa_type_7_default_delete(struct ospf6 *ospf6,
847 struct ospf6_area *oa)
848{
849 struct ospf6_lsa *lsa;
850
851 lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7), 0,
852 oa->ospf6->router_id, oa->lsdb);
853 if (lsa && !OSPF6_LSA_IS_MAXAGE(lsa)) {
854 if (IS_OSPF6_DEBUG_NSSA)
855 zlog_debug(
856 "Withdrawing Type-7 default route from area %s",
857 oa->name);
858
859 ospf6_lsa_purge(lsa);
860 }
861}
862
863/* NSSA Type-7 default route. */
864void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
865{
866 struct listnode *node;
867 struct ospf6_area *oa;
868
869 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
870 if (IS_AREA_NSSA(oa) && oa->nssa_default_originate.enabled
871 && (IS_OSPF6_ABR(ospf6)
872 || (IS_OSPF6_ASBR(ospf6)
873 && ospf6->nssa_default_import_check.status)))
874 ospf6_abr_nssa_type_7_default_create(ospf6, oa);
875 else
876 ospf6_abr_nssa_type_7_default_delete(ospf6, oa);
877 }
878}
879
ad500b22
K
880static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
881{
ad500b22
K
882 if (IS_OSPF6_DEBUG_NSSA)
883 zlog_debug("Check for NSSA-ABR Tasks():");
884
885 if (!IS_OSPF6_ABR(ospf6)) {
886 if (IS_OSPF6_DEBUG_NSSA)
887 zlog_debug("%s Not ABR", __func__);
888 return;
889 }
890
891 if (!ospf6->anyNSSA) {
892 if (IS_OSPF6_DEBUG_NSSA)
893 zlog_debug("%s Not NSSA", __func__);
894 return;
895 }
896
897 /* Each area must confirm TranslatorRole */
898 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 899 zlog_debug("%s: Start", __func__);
ad500b22
K
900
901 /* For all Global Entries flagged "local-translate", unset APPROVED */
902 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 903 zlog_debug("%s: unapprove translates", __func__);
ad500b22
K
904
905 ospf6_abr_unapprove_translates(ospf6);
906
3c77bc80 907 /* Originate Type-7 aggregates */
ad500b22 908 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 909 zlog_debug("%s: send NSSA aggregates", __func__);
3c77bc80 910 ospf6_abr_send_nssa_aggregates(ospf6);
ad500b22
K
911
912 /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
913 * Aggregate as Type-7
914 * Install or Approve in Type-5 Global LSDB
915 */
916 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 917 zlog_debug("%s: process translates", __func__);
ad500b22
K
918 ospf6_abr_process_nssa_translates(ospf6);
919
ad500b22
K
920 /* Flush any unapproved previous translates from Global Data Base */
921 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 922 zlog_debug("%s: remove unapproved translates", __func__);
ad500b22
K
923 ospf6_abr_remove_unapproved_translates(ospf6);
924
ad500b22 925 if (IS_OSPF6_DEBUG_NSSA)
d8da8a4a 926 zlog_debug("%s: Stop", __func__);
ad500b22
K
927}
928
929int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
930 int type)
931{
932 route_map_result_t ret;
933 struct prefix *prefix;
934 struct ospf6_redist *red;
935
936 if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
937 return 0;
938
939 prefix = &route->prefix;
940
941 red = ospf6_redist_lookup(ospf6, type, 0);
942 if (!red)
943 return 0;
944
945 /* Change to new redist structure */
946 if (ROUTEMAP_NAME(red)) {
947 if (ROUTEMAP(red) == NULL)
948 ospf6_asbr_routemap_update(NULL);
949 if (ROUTEMAP(red) == NULL) {
950 zlog_warn(
951 "route-map \"%s\" not found, suppress redistributing",
952 ROUTEMAP_NAME(red));
953 return 0;
954 }
955 }
956
957 /* Change to new redist structure */
958 if (ROUTEMAP(red)) {
959 ret = route_map_apply(ROUTEMAP(red), prefix, route);
960 if (ret == RMAP_DENYMATCH) {
961 if (IS_OSPF6_DEBUG_ASBR)
962 zlog_debug("Denied by route-map \"%s\"",
963 ROUTEMAP_NAME(red));
964 return 0;
965 }
966 }
967
968 return 1;
969}
970
ad500b22
K
971/* This function performs ABR related processing */
972static int ospf6_abr_task_timer(struct thread *thread)
973{
974 struct ospf6 *ospf6 = THREAD_ARG(thread);
975
ad500b22
K
976 if (IS_OSPF6_DEBUG_ABR)
977 zlog_debug("Running ABR task on timer");
978
95b3f03d 979 (void)ospf6_check_and_set_router_abr(ospf6);
ad500b22
K
980 ospf6_abr_nssa_check_status(ospf6);
981 ospf6_abr_task(ospf6);
982 /* if nssa-abr, then scan Type-7 LSDB */
983 ospf6_abr_nssa_task(ospf6);
ad500b22
K
984
985 return 0;
986}
987
988void ospf6_schedule_abr_task(struct ospf6 *ospf6)
989{
990 if (ospf6->t_abr_task) {
991 if (IS_OSPF6_DEBUG_ABR)
992 zlog_debug("ABR task already scheduled");
993 return;
994 }
995
996 if (IS_OSPF6_DEBUG_ABR)
997 zlog_debug("Scheduling ABR task");
998
999 thread_add_timer(master, ospf6_abr_task_timer, ospf6,
1000 OSPF6_ABR_TASK_DELAY, &ospf6->t_abr_task);
1001}
1002
1003/* Flush the NSSA LSAs from the area */
1004static void ospf6_nssa_flush_area(struct ospf6_area *area)
1005{
1006 uint16_t type;
1007 struct ospf6_lsa *lsa = NULL, *type5 = NULL;
1008 struct ospf6 *ospf6 = area->ospf6;
ad500b22
K
1009
1010 if (IS_OSPF6_DEBUG_NSSA)
1011 zlog_debug("%s: area %s", __func__, area->name);
1012
1013 /* Flush the NSSA LSA */
1014 type = htons(OSPF6_LSTYPE_TYPE_7);
ccfffce4 1015 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
ad500b22
K
1016 lsa->header->age = htons(OSPF_LSA_MAXAGE);
1017 SET_FLAG(lsa->flag, OSPF6_LSA_FLUSH);
1018 ospf6_flood(NULL, lsa);
ccfffce4 1019
ad500b22 1020 /* Flush the translated LSA */
95b3f03d 1021 if (ospf6_check_and_set_router_abr(ospf6)) {
ad500b22 1022 type5 = ospf6_lsdb_lookup(
18529688 1023 htons(OSPF6_LSTYPE_AS_EXTERNAL),
1024 lsa->external_lsa_id, ospf6->router_id,
1025 ospf6->lsdb);
ad500b22
K
1026 if (type5
1027 && CHECK_FLAG(type5->flag, OSPF6_LSA_LOCAL_XLT)) {
1028 type5->header->age = htons(OSPF_LSA_MAXAGE);
1029 SET_FLAG(type5->flag, OSPF6_LSA_FLUSH);
1030 ospf6_flood(NULL, type5);
1031 }
1032 }
ad500b22
K
1033 }
1034}
1035
c3a70f65 1036static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
ad500b22
K
1037{
1038 struct ospf6_route *route;
c3a70f65 1039 struct route_node *rn = NULL;
c3a70f65
MR
1040 struct ospf6_external_aggr_rt *aggr;
1041
1042 /* Loop through the external_table to find the LSAs originated
1043 * without aggregation and originate type-7 LSAs for them.
1044 */
1045 for (route = ospf6_route_head(
1046 area->ospf6->external_table);
1047 route; route = ospf6_route_next(route)) {
210429c7
RW
1048 struct ospf6_external_info *info = route->route_option;
1049
c3a70f65 1050 /* This means the Type-5 LSA was originated for this route */
210429c7 1051 if (route->path.origin.id != 0 && info->type != DEFAULT_ROUTE)
6735622c 1052 ospf6_nssa_lsa_originate(route, area, true);
c3a70f65 1053 }
ad500b22 1054
c3a70f65
MR
1055 /* Loop through the aggregation table to originate type-7 LSAs
1056 * for the aggregated type-5 LSAs
1057 */
1058 for (rn = route_top(area->ospf6->rt_aggr_tbl); rn;
1059 rn = route_next(rn)) {
1060 if (!rn->info)
1061 continue;
ad500b22 1062
c3a70f65
MR
1063 aggr = rn->info;
1064
1065 if (CHECK_FLAG(aggr->aggrflags,
1066 OSPF6_EXTERNAL_AGGRT_ORIGINATED)) {
c405b00f
MR
1067 if (IS_OSPF6_DEBUG_NSSA)
1068 zlog_debug(
1069 "Originating Type-7 LSAs for area %s",
1070 area->name);
1071
6735622c 1072 ospf6_nssa_lsa_originate(aggr->route, area, true);
c3a70f65
MR
1073 }
1074 }
1075
1076}
1077
0c293b92 1078void ospf6_area_nssa_update(struct ospf6_area *area)
c3a70f65 1079{
ad500b22 1080 if (IS_AREA_NSSA(area)) {
d36a6a19 1081 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
ad500b22
K
1082 area->ospf6->anyNSSA++;
1083 OSPF6_OPT_SET(area->options, OSPF6_OPT_N);
1084 area->NSSATranslatorRole = OSPF6_NSSA_ROLE_CANDIDATE;
1085 } else if (IS_AREA_ENABLED(area)) {
1086 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
1087 zlog_debug("Normal area for if %s", area->name);
1088 OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_N);
d36a6a19 1089 OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
ad500b22
K
1090 area->ospf6->anyNSSA--;
1091 area->NSSATranslatorState = OSPF6_NSSA_TRANSLATE_DISABLED;
1092 }
1093
1094 /* Refresh router LSA */
1095 if (IS_AREA_NSSA(area)) {
1096 OSPF6_ROUTER_LSA_SCHEDULE(area);
1097
dd551b9d
RW
1098 /* Flush external LSAs. */
1099 ospf6_asbr_remove_externals_from_area(area);
1100
ad500b22 1101 /* Check if router is ABR */
95b3f03d 1102 if (ospf6_check_and_set_router_abr(area->ospf6)) {
ad500b22
K
1103 if (IS_OSPF6_DEBUG_NSSA)
1104 zlog_debug("Router is ABR area %s", area->name);
1105 ospf6_schedule_abr_task(area->ospf6);
1106 } else {
1107 /* Router is not ABR */
1108 if (IS_OSPF6_DEBUG_NSSA)
1109 zlog_debug("NSSA area %s", area->name);
1110
1111 /* Originate NSSA LSA */
c3a70f65 1112 ospf6_check_and_originate_type7_lsa(area);
ad500b22
K
1113 }
1114 } else {
1115 /* Disable NSSA */
1116 if (IS_OSPF6_DEBUG_NSSA)
1117 zlog_debug("Normal area %s", area->name);
1118 ospf6_nssa_flush_area(area);
ad500b22
K
1119 }
1120}
1121
1122int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area)
1123{
1124
1125 if (!IS_AREA_NSSA(area)) {
0c293b92
RW
1126 /* Disable stub first. */
1127 ospf6_area_stub_unset(ospf6, area);
1128
ad500b22
K
1129 SET_FLAG(area->flag, OSPF6_AREA_NSSA);
1130 if (IS_OSPF6_DEBUG_NSSA)
1131 zlog_debug("area %s nssa set", area->name);
1132 ospf6_area_nssa_update(area);
1133 }
1134
1135 return 1;
1136}
1137
1138int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
1139{
1140 if (IS_AREA_NSSA(area)) {
1141 UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
1142 if (IS_OSPF6_DEBUG_NSSA)
1143 zlog_debug("area %s nssa reset", area->name);
3c77bc80
RW
1144
1145 /* Clear the table of NSSA ranges. */
1146 ospf6_route_table_delete(area->nssa_range_table);
1147 area->nssa_range_table =
1148 OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
1149 area->nssa_range_table->scope = area;
1150
ad500b22
K
1151 ospf6_area_nssa_update(area);
1152 }
1153
1154 return 1;
1155}
1156
1157/* Find the NSSA forwarding address */
1158static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
1159{
1160 struct listnode *node, *nnode;
1161 struct ospf6_interface *oi;
1162
1163 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
5f2fe4bb
RW
1164 struct in6_addr *addr;
1165
1166 if (!if_is_operative(oi->interface))
1167 continue;
1168
1169 addr = ospf6_interface_get_global_address(oi->interface);
1170 if (addr)
1171 return addr;
ad500b22
K
1172 }
1173 return NULL;
1174}
1175
1176void ospf6_nssa_lsa_originate(struct ospf6_route *route,
6735622c 1177 struct ospf6_area *area, bool p_bit)
ad500b22
K
1178{
1179 char buffer[OSPF6_MAX_LSASIZE];
1180 struct ospf6_lsa_header *lsa_header;
1181 struct ospf6_lsa *lsa;
1182 struct ospf6_external_info *info = route->route_option;
1183 struct in6_addr *fwd_addr;
1184
1185 struct ospf6_as_external_lsa *as_external_lsa;
ad500b22
K
1186 caddr_t p;
1187
96cad171
MR
1188 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL))
1189 zlog_debug("Originate NSSA-LSA for %pFX", &route->prefix);
ad500b22
K
1190
1191 /* prepare buffer */
1192 memset(buffer, 0, sizeof(buffer));
1193 lsa_header = (struct ospf6_lsa_header *)buffer;
1194 as_external_lsa = (struct ospf6_as_external_lsa
1195 *)((caddr_t)lsa_header
1196 + sizeof(struct ospf6_lsa_header));
1197 p = (caddr_t)((caddr_t)as_external_lsa
1198 + sizeof(struct ospf6_as_external_lsa));
1199
1200 /* Fill AS-External-LSA */
1201 /* Metric type */
242a9767 1202 if (route->path.metric_type == 2)
ad500b22
K
1203 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1204 else
1205 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1206
1207 /* external route tag */
6735622c 1208 if (info && info->tag)
ad500b22
K
1209 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1210 else
1211 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1212
1213 /* Set metric */
1214 OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
1215
1216 /* prefixlen */
1217 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
1218
1219 /* PrefixOptions */
4699ad72 1220 as_external_lsa->prefix.prefix_options = route->prefix_options;
ad500b22
K
1221
1222 /* Set the P bit */
6735622c
RW
1223 if (p_bit)
1224 as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
ad500b22
K
1225
1226 /* don't use refer LS-type */
1227 as_external_lsa->prefix.prefix_refer_lstype = htons(0);
1228
1229 /* set Prefix */
1230 memcpy(p, &route->prefix.u.prefix6,
1231 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
1232 ospf6_prefix_apply_mask(&as_external_lsa->prefix);
1233 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
1234
1235 /* Forwarding address */
1236 fwd_addr = ospf6_get_nssa_fwd_addr(area);
1237 if (fwd_addr) {
1238 memcpy(p, fwd_addr, sizeof(struct in6_addr));
1239 p += sizeof(struct in6_addr);
1240 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1241 } else
1242 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1243
1244 /* External Route Tag */
6735622c
RW
1245 if (info
1246 && CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
ad500b22
K
1247 route_tag_t network_order = htonl(info->tag);
1248
1249 memcpy(p, &network_order, sizeof(network_order));
1250 p += sizeof(network_order);
1251 }
1252
1253 /* Fill LSA Header */
1254 lsa_header->age = 0;
1255 lsa_header->type = htons(OSPF6_LSTYPE_TYPE_7);
1256 lsa_header->id = route->path.origin.id;
1257 lsa_header->adv_router = area->ospf6->router_id;
1258 lsa_header->seqnum =
1259 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
96cad171 1260 lsa_header->adv_router, area->lsdb);
ad500b22
K
1261 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
1262
1263 /* LSA checksum */
1264 ospf6_lsa_checksum(lsa_header);
1265 /* create LSA */
1266 lsa = ospf6_lsa_create(lsa_header);
1267
1268 /* Originate */
1269 ospf6_lsa_originate_area(lsa, area);
1270}
1271
1272void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
1273 struct ospf6_lsa *lsa)
1274{
1275 struct ospf6_lsa *type5 = NULL;
1276 struct ospf6 *ospf6 = area->ospf6;
1277
1278 if (IS_OSPF6_DEBUG_NSSA)
1279 zlog_debug("%s : start", __func__);
1280
8ee9d58b
RW
1281 if (!ospf6_check_and_set_router_abr(ospf6))
1282 return;
1283
ad500b22
K
1284 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1285 lsa->external_lsa_id, ospf6->router_id,
1286 ospf6->lsdb);
8ee9d58b 1287 if (!type5) {
ad500b22
K
1288 if (IS_OSPF6_DEBUG_NSSA)
1289 zlog_debug("%s : Originating type5 LSA", __func__);
1290 ospf6_lsa_translated_nssa_new(area, lsa);
1291 }
1292}
1293
3c77bc80
RW
1294DEFPY (area_nssa_range,
1295 area_nssa_range_cmd,
1296 "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
1297 "OSPF6 area parameters\n"
1298 "OSPF6 area ID in IP address format\n"
1299 "OSPF6 area ID as a decimal value\n"
1300 "Configure OSPF6 area as nssa\n"
1301 "Configured address range\n"
1302 "Specify IPv6 prefix\n"
1303 "Do not advertise\n"
1304 "User specified metric for this range\n"
1305 "Advertised metric for this range\n")
1306{
1307 struct ospf6_area *oa;
1308 struct ospf6_route *range;
1309
1310 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1311
1312 OSPF6_CMD_AREA_GET(area, oa, ospf6);
1313
1314 if (!IS_AREA_NSSA(oa)) {
1315 vty_out(vty, "%% First configure %s as an NSSA area\n", area);
1316 return CMD_WARNING;
1317 }
1318
1319 range = ospf6_route_lookup((struct prefix *)prefix,
1320 oa->nssa_range_table);
1321 if (range == NULL) {
1322 range = ospf6_route_create(ospf6);
1323 range->type = OSPF6_DEST_TYPE_RANGE;
1324 SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE);
1325 prefix_copy(&range->prefix, prefix);
1326 range->path.area_id = oa->area_id;
1327 range->path.metric_type = 2;
1328 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
1329 range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7);
1330 range->path.origin.id = htonl(ospf6->external_id++);
1331 range->path.origin.adv_router = ospf6->router_id;
1332 ospf6_route_add(range, oa->nssa_range_table);
1333 }
1334
1335 /* process "not-advertise" */
1336 if (not_adv)
1337 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
1338 else
1339 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
1340
1341 /* process "cost" */
1342 if (!cost_str)
1343 cost = OSPF_AREA_RANGE_COST_UNSPEC;
1344 range->path.u.cost_config = cost;
1345
1346 /* Redo summaries if required */
1347 if (ospf6_check_and_set_router_abr(ospf6))
1348 ospf6_schedule_abr_task(ospf6);
1349
1350 return CMD_SUCCESS;
1351}
1352
1353DEFPY (no_area_nssa_range,
1354 no_area_nssa_range_cmd,
1355 "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
1356 NO_STR
1357 "OSPF6 area parameters\n"
1358 "OSPF6 area ID in IP address format\n"
1359 "OSPF6 area ID as a decimal value\n"
1360 "Configure OSPF6 area as nssa\n"
1361 "Configured address range\n"
1362 "Specify IPv6 prefix\n"
1363 "Do not advertise\n"
1364 "User specified metric for this range\n"
1365 "Advertised metric for this range\n")
1366{
1367 struct ospf6_area *oa;
1368 struct ospf6_route *range;
1369
1370 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1371
1372 OSPF6_CMD_AREA_GET(area, oa, ospf6);
1373
1374 range = ospf6_route_lookup((struct prefix *)prefix,
1375 oa->nssa_range_table);
1376 if (range == NULL) {
416721d9 1377 vty_out(vty, "%% range %s does not exist.\n", prefix_str);
3c77bc80
RW
1378 return CMD_SUCCESS;
1379 }
1380
1381 if (ospf6_check_and_set_router_abr(oa->ospf6)) {
1382 /* Blow away the aggregated LSA and route */
1383 SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
1384
1385 /* Redo summaries if required */
1386 thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
1387 }
1388
1389 ospf6_route_remove(range, oa->nssa_range_table);
1390
1391 return CMD_SUCCESS;
1392}
1393
ad500b22
K
1394DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
1395 "debug ospf6 nssa",
1396 DEBUG_STR
1397 OSPF6_STR
1398 "Debug OSPFv3 NSSA function\n")
1399{
1400 OSPF6_DEBUG_NSSA_ON();
1401 return CMD_SUCCESS;
1402}
1403
1404DEFUN(no_debug_ospf6_nssa, no_debug_ospf6_nssa_cmd,
1405 "no debug ospf6 nssa",
1406 NO_STR
1407 DEBUG_STR
1408 OSPF6_STR
1409 "Debug OSPFv3 NSSA function\n")
1410{
1411 OSPF6_DEBUG_NSSA_OFF();
1412 return CMD_SUCCESS;
1413}
1414
1415void config_write_ospf6_debug_nssa(struct vty *vty)
1416{
1417 if (IS_OSPF6_DEBUG_NSSA)
1418 vty_out(vty, "debug ospf6 nssa\n");
1419}
1420
1421void install_element_ospf6_debug_nssa(void)
1422{
3c77bc80
RW
1423 install_element(OSPF6_NODE, &area_nssa_range_cmd);
1424 install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
1425
ad500b22
K
1426 install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
1427 install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
1428 install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
1429 install_element(CONFIG_NODE, &no_debug_ospf6_nssa_cmd);
1430}