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