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