2 * OSPFv3 Not So Stubby Area implementation.
4 * Copyright (C) 2021 Kaushik Nath
5 * Copyright (C) 2021 Soman K.S
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.
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.
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.
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"
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_neighbor.h"
46 #include "ospf6_flood.h"
47 #include "ospf6_intra.h"
48 #include "ospf6_abr.h"
49 #include "ospf6_asbr.h"
51 #include "ospf6_nssa.h"
52 #include "ospf6d/ospf6_nssa_clippy.c"
54 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA
, "OSPF6 LSA");
55 unsigned char config_debug_ospf6_nssa
= 0;
56 /* Determine whether this router is elected translator or not for area */
57 static int ospf6_abr_nssa_am_elected(struct ospf6_area
*oa
)
59 struct ospf6_lsa
*lsa
;
60 struct ospf6_router_lsa
*router_lsa
;
61 in_addr_t
*best
= NULL
;
64 type
= htons(OSPF6_LSTYPE_ROUTER
);
66 /* Verify all the router LSA to compare the router ID */
67 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
)) {
69 router_lsa
= (struct ospf6_router_lsa
70 *)((caddr_t
)lsa
->header
71 + sizeof(struct ospf6_lsa_header
));
73 /* ignore non-ABR routers */
74 if (!CHECK_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
))
77 /* Router has Nt flag - always translate */
78 if (CHECK_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
)) {
79 if (IS_OSPF6_DEBUG_NSSA
)
80 zlog_debug("%s: router %pI4 asserts Nt",
81 __func__
, &lsa
->header
->id
);
86 best
= &lsa
->header
->adv_router
;
87 else if (IPV4_ADDR_CMP(best
, &lsa
->header
->adv_router
) < 0)
88 best
= &lsa
->header
->adv_router
;
92 if (IS_OSPF6_DEBUG_NSSA
)
93 zlog_debug("%s: best electable ABR not found",
98 if (IS_OSPF6_DEBUG_NSSA
)
99 zlog_debug("%s: best electable ABR is: %pI4", __func__
, best
);
101 if (IPV4_ADDR_CMP(best
, &oa
->ospf6
->router_id
) <= 0) {
102 if (IS_OSPF6_DEBUG_NSSA
)
103 zlog_debug("%s: elected ABR is: %pI4", __func__
, best
);
106 if (IS_OSPF6_DEBUG_NSSA
)
107 zlog_debug("%s: not elected best %pI4, router ID %pI4",
108 __func__
, best
, &oa
->ospf6
->router_id
);
113 /* Flush the translated LSA when translation is disabled */
114 static void ospf6_flush_translated_lsa(struct ospf6_area
*area
)
117 struct ospf6_lsa
*type7
;
118 struct ospf6_lsa
*type5
;
119 struct ospf6
*ospf6
= area
->ospf6
;
121 if (IS_OSPF6_DEBUG_NSSA
)
122 zlog_debug("%s: start area %s", __func__
, area
->name
);
124 type
= htons(OSPF6_LSTYPE_TYPE_7
);
125 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
, type7
)) {
126 type5
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
127 type7
->external_lsa_id
,
128 ospf6
->router_id
, ospf6
->lsdb
);
129 if (type5
&& CHECK_FLAG(type5
->flag
, OSPF6_LSA_LOCAL_XLT
))
130 ospf6_lsa_premature_aging(type5
);
132 if (IS_OSPF6_DEBUG_NSSA
)
133 zlog_debug("%s: finish area %s", __func__
, area
->name
);
136 /* Check NSSA status for all nssa areas */
137 void ospf6_abr_nssa_check_status(struct ospf6
*ospf6
)
139 struct ospf6_area
*area
;
140 struct listnode
*lnode
, *nnode
;
142 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, nnode
, area
)) {
143 uint8_t old_state
= area
->NSSATranslatorState
;
145 if (IS_OSPF6_DEBUG_NSSA
)
146 zlog_debug("%s: checking area %s flag %x", __func__
,
147 area
->name
, area
->flag
);
149 if (!IS_AREA_NSSA(area
))
152 if (!CHECK_FLAG(area
->ospf6
->flag
, OSPF6_FLAG_ABR
)) {
153 if (IS_OSPF6_DEBUG_NSSA
)
154 zlog_debug("%s: not ABR", __func__
);
155 area
->NSSATranslatorState
=
156 OSPF6_NSSA_TRANSLATE_DISABLED
;
157 ospf6_flush_translated_lsa(area
);
160 if (area
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
161 area
->NSSATranslatorState
=
162 OSPF6_NSSA_TRANSLATE_ENABLED
;
164 /* We are a candidate for Translation */
165 if (ospf6_abr_nssa_am_elected(area
) > 0) {
166 area
->NSSATranslatorState
=
167 OSPF6_NSSA_TRANSLATE_ENABLED
;
168 if (IS_OSPF6_DEBUG_NSSA
)
170 "%s: elected translator",
173 area
->NSSATranslatorState
=
174 OSPF6_NSSA_TRANSLATE_DISABLED
;
175 ospf6_flush_translated_lsa(area
);
176 if (IS_OSPF6_DEBUG_NSSA
)
177 zlog_debug("%s: not elected",
184 * All NSSA border routers must set the E-bit in the Type-1
185 * router-LSAs of their directly attached non-stub areas, even
186 * when they are not translating.
188 if (old_state
!= area
->NSSATranslatorState
) {
189 if (old_state
== OSPF6_NSSA_TRANSLATE_DISABLED
) {
190 ++ospf6
->redist_count
;
191 ospf6_asbr_status_update(ospf6
,
192 ospf6
->redist_count
);
194 --ospf6
->redist_count
;
195 ospf6_asbr_status_update(ospf6
,
196 ospf6
->redist_count
);
202 /* Mark the summary LSA's as unapproved, when ABR status changes.*/
203 static void ospf6_abr_unapprove_summaries(struct ospf6
*ospf6
)
205 struct listnode
*node
, *nnode
;
206 struct ospf6_area
*area
;
207 struct ospf6_lsa
*lsa
;
210 if (IS_OSPF6_DEBUG_ABR
)
211 zlog_debug("%s : Start", __func__
);
213 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
)) {
214 if (IS_OSPF6_DEBUG_ABR
)
215 zlog_debug("%s : considering area %pI4", __func__
,
217 /* Inter area router LSA */
218 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
219 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
221 if (IS_OSPF6_DEBUG_ABR
)
223 "%s : approved unset on summary link id %pI4",
224 __func__
, &lsa
->header
->id
);
225 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
227 /* Inter area prefix LSA */
228 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
229 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
231 if (IS_OSPF6_DEBUG_ABR
)
233 "%s : approved unset on asbr-summary link id %pI4",
234 __func__
, &lsa
->header
->id
);
235 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
239 if (IS_OSPF6_DEBUG_ABR
)
240 zlog_debug("%s : Stop", __func__
);
243 /* Re-advertise inter-area router LSA's */
244 void ospf6_asbr_prefix_readvertise(struct ospf6
*ospf6
)
246 struct ospf6_route
*brouter
;
247 struct listnode
*node
, *nnode
;
248 struct ospf6_area
*oa
;
250 if (IS_OSPF6_DEBUG_ABR
)
251 zlog_debug("Re-examining Inter-Router prefixes");
254 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
255 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
);
256 brouter
; brouter
= ospf6_route_next(brouter
))
257 ospf6_abr_originate_summary_to_area(brouter
, oa
);
260 if (IS_OSPF6_DEBUG_ABR
)
261 zlog_debug("Finished re-examining Inter-Router prefixes");
264 /* Advertise prefixes configured using area <area-id> range command */
265 static void ospf6_abr_announce_aggregates(struct ospf6
*ospf6
)
267 struct ospf6_area
*area
;
268 struct ospf6_route
*range
;
269 struct listnode
*node
;
271 if (IS_OSPF6_DEBUG_ABR
)
272 zlog_debug("%s: Start", __func__
);
274 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, area
)) {
275 if (IS_OSPF6_DEBUG_ABR
)
277 "ospf_abr_announce_aggregates(): looking at area %pI4",
280 for (range
= ospf6_route_head(area
->range_table
); range
;
281 range
= ospf6_route_next(range
))
282 ospf6_abr_range_update(range
, ospf6
);
285 if (IS_OSPF6_DEBUG_ABR
)
286 zlog_debug("%s: Stop", __func__
);
289 /* Flush the summary LSA's which are not approved.*/
290 void ospf6_abr_remove_unapproved_summaries(struct ospf6
*ospf6
)
292 struct listnode
*node
, *nnode
;
293 struct ospf6_area
*area
;
294 struct ospf6_lsa
*lsa
;
297 if (IS_OSPF6_DEBUG_ABR
)
298 zlog_debug("%s : Start", __func__
);
300 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
)) {
301 if (IS_OSPF6_DEBUG_ABR
)
302 zlog_debug("%s : looking at area %pI4", __func__
,
305 /* Inter area router LSA */
306 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
307 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
309 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
))
310 ospf6_lsa_premature_aging(lsa
);
313 /* Inter area prefix LSA */
314 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
315 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
317 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
))
318 ospf6_lsa_premature_aging(lsa
);
322 if (IS_OSPF6_DEBUG_ABR
)
323 zlog_debug("%s : Stop", __func__
);
327 * This is the function taking care about ABR stuff, i.e.
328 * summary-LSA origination and flooding.
330 static void ospf6_abr_task(struct ospf6
*ospf6
)
332 if (IS_OSPF6_DEBUG_ABR
)
333 zlog_debug("%s : Start", __func__
);
335 if (ospf6
->route_table
== NULL
|| ospf6
->brouter_table
== NULL
) {
336 if (IS_OSPF6_DEBUG_ABR
)
337 zlog_debug("%s : Routing tables are not yet ready",
342 ospf6_abr_unapprove_summaries(ospf6
);
344 if (IS_OSPF6_DEBUG_ABR
)
345 zlog_debug("%s : prepare aggregates", __func__
);
347 ospf6_abr_range_reset_cost(ospf6
);
349 if (IS_OSPF6_ABR(ospf6
)) {
350 if (IS_OSPF6_DEBUG_ABR
)
351 zlog_debug("%s : process network RT", __func__
);
352 ospf6_abr_prefix_resummarize(ospf6
);
354 if (IS_OSPF6_DEBUG_ABR
)
355 zlog_debug("%s : process router RT", __func__
);
356 ospf6_asbr_prefix_readvertise(ospf6
);
358 if (IS_OSPF6_DEBUG_ABR
)
359 zlog_debug("%s : announce aggregates", __func__
);
360 ospf6_abr_announce_aggregates(ospf6
);
362 if (IS_OSPF6_DEBUG_ABR
)
363 zlog_debug("%s : announce stub defaults", __func__
);
364 ospf6_abr_defaults_to_stub(ospf6
);
366 if (IS_OSPF6_DEBUG_ABR
)
367 zlog_debug("%s : announce NSSA Type-7 defaults",
369 ospf6_abr_nssa_type_7_defaults(ospf6
);
372 if (IS_OSPF6_DEBUG_ABR
)
373 zlog_debug("%s : remove unapproved summaries", __func__
);
374 ospf6_abr_remove_unapproved_summaries(ospf6
);
376 if (IS_OSPF6_DEBUG_ABR
)
377 zlog_debug("%s : Stop", __func__
);
380 /* For NSSA Translations
381 * Mark the translated LSA's as unapproved. */
382 static void ospf6_abr_unapprove_translates(struct ospf6
*ospf6
)
384 struct ospf6_lsa
*lsa
;
387 if (IS_OSPF6_DEBUG_NSSA
)
388 zlog_debug("%s: Start", __func__
);
390 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
391 for (ALL_LSDB_TYPED(ospf6
->lsdb
, type
, lsa
)) {
392 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
393 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
394 if (IS_OSPF6_DEBUG_NSSA
)
396 "%s : approved unset on link id %pI4",
397 __func__
, &lsa
->header
->id
);
401 if (IS_OSPF6_DEBUG_NSSA
)
402 zlog_debug("%s: Stop", __func__
);
405 /* Generate the translated external lsa from NSSA lsa */
406 static struct ospf6_lsa
*ospf6_lsa_translated_nssa_new(struct ospf6_area
*area
,
407 struct ospf6_lsa
*type7
)
409 char buffer
[OSPF6_MAX_LSASIZE
];
410 struct ospf6_lsa
*lsa
;
411 struct ospf6_as_external_lsa
*ext
, *extnew
;
412 struct ospf6_lsa_header
*lsa_header
;
413 caddr_t old_ptr
, new_ptr
;
414 struct ospf6_as_external_lsa
*nssa
;
415 struct prefix prefix
;
416 struct ospf6
*ospf6
= area
->ospf6
;
417 ptrdiff_t tag_offset
= 0;
418 route_tag_t network_order
;
419 struct ospf6_route
*range
;
421 if (IS_OSPF6_DEBUG_NSSA
)
422 zlog_debug("%s : Start", __func__
);
424 if (area
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
) {
425 if (IS_OSPF6_DEBUG_NSSA
)
426 zlog_debug("%s: Translation disabled for area %s",
427 __func__
, area
->name
);
431 /* find the translated Type-5 for this Type-7 */
432 nssa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
434 prefix
.family
= AF_INET6
;
435 prefix
.prefixlen
= nssa
->prefix
.prefix_length
;
436 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, nssa
, &nssa
->prefix
);
438 /* Check if the Type-7 LSA should be suppressed by aggregation. */
439 range
= ospf6_route_lookup_bestmatch(&prefix
, area
->nssa_range_table
);
440 if (range
&& !prefix_same(&prefix
, &range
->prefix
)
441 && !CHECK_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
)) {
442 if (IS_OSPF6_DEBUG_NSSA
)
444 "%s: LSA %s suppressed by range %pFX of area %s",
445 __func__
, type7
->name
, &range
->prefix
,
451 memset(buffer
, 0, sizeof(buffer
));
452 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
453 extnew
= (struct ospf6_as_external_lsa
454 *)((caddr_t
)lsa_header
455 + sizeof(struct ospf6_lsa_header
));
456 ext
= (struct ospf6_as_external_lsa
457 *)((caddr_t
)(type7
->header
)
458 + sizeof(struct ospf6_lsa_header
));
460 (caddr_t
)((caddr_t
)ext
+ sizeof(struct ospf6_as_external_lsa
));
461 new_ptr
= (caddr_t
)((caddr_t
)extnew
462 + sizeof(struct ospf6_as_external_lsa
));
464 memcpy(extnew
, ext
, sizeof(struct ospf6_as_external_lsa
));
467 memcpy(new_ptr
, old_ptr
, OSPF6_PREFIX_SPACE(ext
->prefix
.prefix_length
));
468 ospf6_prefix_apply_mask(&extnew
->prefix
);
469 new_ptr
+= OSPF6_PREFIX_SPACE(extnew
->prefix
.prefix_length
);
472 sizeof(*ext
) + OSPF6_PREFIX_SPACE(ext
->prefix
.prefix_length
);
474 /* Forwarding address */
475 if (CHECK_FLAG(ext
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
476 memcpy(new_ptr
, (caddr_t
)ext
+ tag_offset
,
477 sizeof(struct in6_addr
));
478 new_ptr
+= sizeof(struct in6_addr
);
479 tag_offset
+= sizeof(struct in6_addr
);
481 /* External Route Tag */
482 if (CHECK_FLAG(ext
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
483 memcpy(&network_order
, (caddr_t
)ext
+ tag_offset
,
484 sizeof(network_order
));
485 network_order
= htonl(network_order
);
486 memcpy(new_ptr
, &network_order
, sizeof(network_order
));
487 new_ptr
+= sizeof(network_order
);
490 /* Fill LSA Header */
492 lsa_header
->type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
493 lsa_header
->id
= htonl(ospf6
->external_id
);
494 ospf6
->external_id
++;
495 lsa_header
->adv_router
= ospf6
->router_id
;
497 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
498 lsa_header
->adv_router
, ospf6
->lsdb
);
499 lsa_header
->length
= htons((caddr_t
)new_ptr
- (caddr_t
)lsa_header
);
500 type7
->external_lsa_id
= lsa_header
->id
;
503 ospf6_lsa_checksum(lsa_header
);
506 lsa
= ospf6_lsa_create(lsa_header
);
508 SET_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
);
509 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
512 ospf6_lsa_originate_process(lsa
, ospf6
);
514 if (IS_OSPF6_DEBUG_NSSA
)
515 zlog_debug("%s: Originated type5 LSA id %pI4", __func__
,
520 /* Delete LSA from retransmission list */
521 static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6
*ospf6
,
522 struct ospf6_lsa
*lsa
)
524 struct listnode
*node
, *nnode
;
525 struct ospf6_area
*area
;
527 if (IS_OSPF6_DEBUG_NSSA
)
528 zlog_debug("%s : start lsa %s", __func__
, lsa
->name
);
530 /*The function ospf6_flood_clear_area removes LSA from
533 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
))
534 ospf6_flood_clear_area(lsa
, area
);
536 if (IS_OSPF6_DEBUG_NSSA
)
537 zlog_debug("%s : finish lsa %s", __func__
, lsa
->name
);
540 /* Refresh translated AS-external-LSA. */
541 struct ospf6_lsa
*ospf6_translated_nssa_refresh(struct ospf6_area
*area
,
542 struct ospf6_lsa
*type7
,
543 struct ospf6_lsa
*type5
)
545 struct ospf6_lsa
*new = NULL
;
546 struct prefix prefix
;
547 struct ospf6
*ospf6
= area
->ospf6
;
549 if (IS_OSPF6_DEBUG_NSSA
)
550 zlog_debug("%s : start area %s", __func__
, area
->name
);
555 /* Find the AS external LSA */
557 struct ospf6_as_external_lsa
*ext_lsa
;
558 struct ospf6_route
*match
;
560 /* Find the AS external LSA from Type-7 LSA */
561 if (IS_OSPF6_DEBUG_NSSA
)
563 "%s: try to find translated Type-5 LSA for %s",
564 __func__
, type7
->name
);
566 ext_lsa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
568 prefix
.family
= AF_INET6
;
569 prefix
.prefixlen
= ext_lsa
->prefix
.prefix_length
;
570 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, ext_lsa
,
573 match
= ospf6_route_lookup(&prefix
, ospf6
->external_table
);
575 type5
= ospf6_lsdb_lookup(
576 htons(OSPF6_LSTYPE_AS_EXTERNAL
),
577 match
->path
.origin
.id
, ospf6
->router_id
,
582 if (CHECK_FLAG(type5
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
583 /* Delete LSA from neighbor retransmit-list. */
584 ospf6_ls_retransmit_delete_nbr_as(ospf6
, type5
);
587 ospf6_lsa_premature_aging(type5
);
589 if (IS_OSPF6_DEBUG_NSSA
)
590 zlog_debug("%s: Invalid translated LSA %s",
591 __func__
, type5
->name
);
596 /* create new translated LSA */
597 if (ospf6_lsa_age_current(type7
) != OSPF_LSA_MAXAGE
) {
598 if ((new = ospf6_lsa_translated_nssa_new(area
, type7
))
600 if (IS_OSPF6_DEBUG_NSSA
)
602 "%s: Could not translate Type-7 for %pI4",
603 __func__
, &type7
->header
->id
);
608 if (IS_OSPF6_DEBUG_NSSA
)
609 zlog_debug("%s: finish", __func__
);
614 static void ospf6_abr_translate_nssa(struct ospf6_area
*area
,
615 struct ospf6_lsa
*lsa
)
617 /* Incoming Type-7 or aggregated Type-7
619 * LSA is skipped if P-bit is off.
621 * The Type-7 is translated, Installed/Approved as a Type-5 into
622 * global LSDB, then Flooded through AS
624 * Later, any Unapproved Translated Type-5's are flushed/discarded
627 struct ospf6_lsa
*old
= NULL
;
628 struct ospf6_as_external_lsa
*nssa_lsa
;
629 struct prefix prefix
;
630 struct ospf6_route
*match
;
634 nssa_lsa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
637 if (!CHECK_FLAG(nssa_lsa
->prefix
.prefix_options
,
638 OSPF6_PREFIX_OPTION_P
)) {
639 if (IS_OSPF6_DEBUG_NSSA
)
641 "%s : LSA Id %pI4, P-bit off, NO Translation",
642 __func__
, &lsa
->header
->id
);
646 if (IS_OSPF6_DEBUG_NSSA
)
648 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
649 __func__
, &lsa
->header
->id
, &lsa
->external_lsa_id
);
651 prefix
.family
= AF_INET6
;
652 prefix
.prefixlen
= nssa_lsa
->prefix
.prefix_length
;
653 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, nssa_lsa
, &nssa_lsa
->prefix
);
655 if (!CHECK_FLAG(nssa_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
656 if (IS_OSPF6_DEBUG_NSSA
)
658 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
659 __func__
, &lsa
->header
->id
);
663 /* Find the type-5 LSA in the area-range table */
664 match
= ospf6_route_lookup_bestmatch(&prefix
, area
->nssa_range_table
);
665 if (match
&& CHECK_FLAG(match
->flag
, OSPF6_ROUTE_NSSA_RANGE
)) {
666 if (prefix_same(&prefix
, &match
->prefix
)) {
667 /* The prefix range is being removed,
671 CHECK_FLAG(match
->flag
, OSPF6_ROUTE_REMOVE
)
674 if (!CHECK_FLAG(match
->flag
, OSPF6_ROUTE_REMOVE
)) {
675 if (IS_OSPF6_DEBUG_NSSA
)
677 "%s: LSA Id %pI4 suppressed by range %pFX of area %s",
678 __func__
, &lsa
->header
->id
,
679 &match
->prefix
, area
->name
);
680 /* LSA will be suppressed by area-range command,
688 /* Find the existing AS-External LSA for this prefix */
689 match
= ospf6_route_lookup(&prefix
, ospf6
->route_table
);
691 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
692 lsa
->external_lsa_id
, ospf6
->router_id
,
696 if (OSPF6_LSA_IS_MAXAGE(lsa
)) {
698 ospf6_lsa_premature_aging(old
);
702 if (old
&& !OSPF6_LSA_IS_MAXAGE(old
)) {
703 if (IS_OSPF6_DEBUG_NSSA
)
705 "%s : found old translated LSA Id %pI4, skip",
706 __func__
, &old
->header
->id
);
708 UNSET_FLAG(old
->flag
, OSPF6_LSA_UNAPPROVED
);
712 /* no existing external route for this LSA Id
713 * originate translated LSA
716 if (ospf6_lsa_translated_nssa_new(area
, lsa
) == NULL
) {
717 if (IS_OSPF6_DEBUG_NSSA
)
719 "%s : Could not translate Type-7 for %pI4 to Type-5",
720 __func__
, &lsa
->header
->id
);
726 static void ospf6_abr_process_nssa_translates(struct ospf6
*ospf6
)
728 /* Scan through all NSSA_LSDB records for all areas;
729 * If P-bit is on, translate all Type-7's to 5's and aggregate or
730 * flood install as approved in Type-5 LSDB with XLATE Flag on
731 * later, do same for all aggregates... At end, DISCARD all
732 * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
734 struct listnode
*node
;
735 struct ospf6_area
*oa
;
736 struct ospf6_lsa
*lsa
;
739 if (IS_OSPF6_DEBUG_NSSA
)
740 zlog_debug("%s : Start", __func__
);
742 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
743 if (!IS_AREA_NSSA(oa
))
746 /* skip if not translator */
747 if (oa
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
) {
748 zlog_debug("%s area %pI4 NSSATranslatorState %d",
749 __func__
, &oa
->area_id
,
750 oa
->NSSATranslatorState
);
754 if (IS_OSPF6_DEBUG_NSSA
)
755 zlog_debug("%s : looking at area %pI4", __func__
,
758 type
= htons(OSPF6_LSTYPE_TYPE_7
);
759 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
)) {
760 zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
761 __func__
, lsa
->name
, &lsa
->header
->id
,
762 &lsa
->header
->adv_router
);
763 ospf6_abr_translate_nssa(oa
, lsa
);
767 if (IS_OSPF6_DEBUG_NSSA
)
768 zlog_debug("%s : Stop", __func__
);
771 static void ospf6_abr_send_nssa_aggregates(struct ospf6
*ospf6
)
773 struct listnode
*node
;
774 struct ospf6_area
*area
;
775 struct ospf6_route
*range
;
777 if (IS_OSPF6_DEBUG_NSSA
)
778 zlog_debug("%s: Start", __func__
);
780 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, area
)) {
781 if (area
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
)
784 if (IS_OSPF6_DEBUG_NSSA
)
785 zlog_debug("%s: looking at area %pI4", __func__
,
788 for (range
= ospf6_route_head(area
->nssa_range_table
); range
;
789 range
= ospf6_route_next(range
))
790 ospf6_abr_range_update(range
, ospf6
);
793 if (IS_OSPF6_DEBUG_NSSA
)
794 zlog_debug("%s: Stop", __func__
);
797 static void ospf6_abr_remove_unapproved_translates(struct ospf6
*ospf6
)
799 struct ospf6_lsa
*lsa
;
802 /* All AREA PROCESS should have APPROVED necessary LSAs */
803 /* Remove any left over and not APPROVED */
804 if (IS_OSPF6_DEBUG_NSSA
)
805 zlog_debug("%s: Start", __func__
);
807 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
808 for (ALL_LSDB_TYPED(ospf6
->lsdb
, type
, lsa
)) {
809 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
)
810 && CHECK_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
)) {
812 "%s : removing unapproved translates, lsa : %s",
813 __func__
, lsa
->name
);
815 ospf6_lsa_premature_aging(lsa
);
819 if (IS_OSPF6_DEBUG_NSSA
)
820 zlog_debug("%s: Stop", __func__
);
823 static void ospf6_abr_nssa_type_7_default_create(struct ospf6
*ospf6
,
824 struct ospf6_area
*oa
)
826 struct ospf6_route
*def
;
830 if (IS_OSPF6_DEBUG_NSSA
)
831 zlog_debug("Announcing Type-7 default route into NSSA area %s",
834 def
= ospf6_route_create(ospf6
);
835 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
836 def
->prefix
.family
= AF_INET6
;
837 def
->prefix
.prefixlen
= 0;
838 memset(&def
->prefix
.u
.prefix6
, 0, sizeof(struct in6_addr
));
839 def
->type
= OSPF6_DEST_TYPE_NETWORK
;
840 def
->path
.subtype
= OSPF6_PATH_SUBTYPE_DEFAULT_RT
;
841 if (CHECK_FLAG(ospf6
->flag
, OSPF6_FLAG_ABR
))
842 def
->path
.area_id
= ospf6
->backbone
->area_id
;
844 def
->path
.area_id
= oa
->area_id
;
846 /* Compute default route type and metric. */
847 if (oa
->nssa_default_originate
.metric_value
!= -1)
848 metric
= oa
->nssa_default_originate
.metric_value
;
850 metric
= DEFAULT_DEFAULT_ALWAYS_METRIC
;
851 if (oa
->nssa_default_originate
.metric_type
!= -1)
852 metric_type
= oa
->nssa_default_originate
.metric_type
;
854 metric_type
= DEFAULT_METRIC_TYPE
;
855 def
->path
.metric_type
= metric_type
;
856 def
->path
.cost
= metric
;
857 if (metric_type
== 1)
858 def
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL1
;
860 def
->path
.type
= OSPF6_PATH_TYPE_EXTERNAL2
;
862 ospf6_nssa_lsa_originate(def
, oa
, false);
863 ospf6_route_delete(def
);
866 static void ospf6_abr_nssa_type_7_default_delete(struct ospf6
*ospf6
,
867 struct ospf6_area
*oa
)
869 struct ospf6_lsa
*lsa
;
871 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_TYPE_7
), 0,
872 oa
->ospf6
->router_id
, oa
->lsdb
);
873 if (lsa
&& !OSPF6_LSA_IS_MAXAGE(lsa
)) {
874 if (IS_OSPF6_DEBUG_NSSA
)
876 "Withdrawing Type-7 default route from area %s",
879 ospf6_lsa_purge(lsa
);
883 /* NSSA Type-7 default route. */
884 void ospf6_abr_nssa_type_7_defaults(struct ospf6
*ospf6
)
886 struct listnode
*node
;
887 struct ospf6_area
*oa
;
889 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
890 if (IS_AREA_NSSA(oa
) && oa
->nssa_default_originate
.enabled
891 && (IS_OSPF6_ABR(ospf6
)
892 || (IS_OSPF6_ASBR(ospf6
)
893 && ospf6
->nssa_default_import_check
.status
)))
894 ospf6_abr_nssa_type_7_default_create(ospf6
, oa
);
896 ospf6_abr_nssa_type_7_default_delete(ospf6
, oa
);
900 static void ospf6_abr_nssa_task(struct ospf6
*ospf6
)
902 if (IS_OSPF6_DEBUG_NSSA
)
903 zlog_debug("Check for NSSA-ABR Tasks():");
905 if (!IS_OSPF6_ABR(ospf6
)) {
906 if (IS_OSPF6_DEBUG_NSSA
)
907 zlog_debug("%s Not ABR", __func__
);
911 if (!ospf6
->anyNSSA
) {
912 if (IS_OSPF6_DEBUG_NSSA
)
913 zlog_debug("%s Not NSSA", __func__
);
917 /* Each area must confirm TranslatorRole */
918 if (IS_OSPF6_DEBUG_NSSA
)
919 zlog_debug("%s: Start", __func__
);
921 /* For all Global Entries flagged "local-translate", unset APPROVED */
922 if (IS_OSPF6_DEBUG_NSSA
)
923 zlog_debug("%s: unapprove translates", __func__
);
925 ospf6_abr_unapprove_translates(ospf6
);
927 /* Originate Type-7 aggregates */
928 if (IS_OSPF6_DEBUG_NSSA
)
929 zlog_debug("%s: send NSSA aggregates", __func__
);
930 ospf6_abr_send_nssa_aggregates(ospf6
);
932 /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
933 * Aggregate as Type-7
934 * Install or Approve in Type-5 Global LSDB
936 if (IS_OSPF6_DEBUG_NSSA
)
937 zlog_debug("%s: process translates", __func__
);
938 ospf6_abr_process_nssa_translates(ospf6
);
940 /* Flush any unapproved previous translates from Global Data Base */
941 if (IS_OSPF6_DEBUG_NSSA
)
942 zlog_debug("%s: remove unapproved translates", __func__
);
943 ospf6_abr_remove_unapproved_translates(ospf6
);
945 if (IS_OSPF6_DEBUG_NSSA
)
946 zlog_debug("%s: Stop", __func__
);
949 int ospf6_redistribute_check(struct ospf6
*ospf6
, struct ospf6_route
*route
,
952 route_map_result_t ret
;
953 struct prefix
*prefix
;
954 struct ospf6_redist
*red
;
956 if (!ospf6_zebra_is_redistribute(type
, ospf6
->vrf_id
))
959 prefix
= &route
->prefix
;
961 red
= ospf6_redist_lookup(ospf6
, type
, 0);
965 /* Change to new redist structure */
966 if (ROUTEMAP_NAME(red
)) {
967 if (ROUTEMAP(red
) == NULL
)
968 ospf6_asbr_routemap_update(NULL
);
969 if (ROUTEMAP(red
) == NULL
) {
971 "route-map \"%s\" not found, suppress redistributing",
977 /* Change to new redist structure */
979 ret
= route_map_apply(ROUTEMAP(red
), prefix
, route
);
980 if (ret
== RMAP_DENYMATCH
) {
981 if (IS_OSPF6_DEBUG_ASBR
)
982 zlog_debug("Denied by route-map \"%s\"",
991 /* This function performs ABR related processing */
992 static void ospf6_abr_task_timer(struct thread
*thread
)
994 struct ospf6
*ospf6
= THREAD_ARG(thread
);
996 if (IS_OSPF6_DEBUG_ABR
)
997 zlog_debug("Running ABR task on timer");
999 (void)ospf6_check_and_set_router_abr(ospf6
);
1000 ospf6_abr_nssa_check_status(ospf6
);
1001 ospf6_abr_task(ospf6
);
1002 /* if nssa-abr, then scan Type-7 LSDB */
1003 ospf6_abr_nssa_task(ospf6
);
1006 void ospf6_schedule_abr_task(struct ospf6
*ospf6
)
1008 if (thread_is_scheduled(ospf6
->t_abr_task
)) {
1009 if (IS_OSPF6_DEBUG_ABR
)
1010 zlog_debug("ABR task already scheduled");
1014 if (IS_OSPF6_DEBUG_ABR
)
1015 zlog_debug("Scheduling ABR task");
1017 thread_add_timer(master
, ospf6_abr_task_timer
, ospf6
,
1018 OSPF6_ABR_TASK_DELAY
, &ospf6
->t_abr_task
);
1021 /* Flush the NSSA LSAs from the area */
1022 static void ospf6_nssa_flush_area(struct ospf6_area
*area
)
1025 struct ospf6_lsa
*lsa
= NULL
, *type5
= NULL
;
1026 struct ospf6
*ospf6
= area
->ospf6
;
1028 if (IS_OSPF6_DEBUG_NSSA
)
1029 zlog_debug("%s: area %s", __func__
, area
->name
);
1031 /* Flush the NSSA LSA */
1032 type
= htons(OSPF6_LSTYPE_TYPE_7
);
1033 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
, lsa
)) {
1034 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
1035 SET_FLAG(lsa
->flag
, OSPF6_LSA_FLUSH
);
1036 ospf6_flood(NULL
, lsa
);
1038 /* Flush the translated LSA */
1039 if (ospf6_check_and_set_router_abr(ospf6
)) {
1040 type5
= ospf6_lsdb_lookup(
1041 htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1042 lsa
->external_lsa_id
, ospf6
->router_id
,
1045 && CHECK_FLAG(type5
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
1046 type5
->header
->age
= htons(OSPF_LSA_MAXAGE
);
1047 SET_FLAG(type5
->flag
, OSPF6_LSA_FLUSH
);
1048 ospf6_flood(NULL
, type5
);
1054 static void ospf6_check_and_originate_type7_lsa(struct ospf6_area
*area
)
1056 struct ospf6_route
*route
;
1057 struct route_node
*rn
= NULL
;
1058 struct ospf6_external_aggr_rt
*aggr
;
1060 /* Loop through the external_table to find the LSAs originated
1061 * without aggregation and originate type-7 LSAs for them.
1063 for (route
= ospf6_route_head(
1064 area
->ospf6
->external_table
);
1065 route
; route
= ospf6_route_next(route
)) {
1066 struct ospf6_external_info
*info
= route
->route_option
;
1068 /* This means the Type-5 LSA was originated for this route */
1069 if (route
->path
.origin
.id
!= 0 && info
->type
!= DEFAULT_ROUTE
)
1070 ospf6_nssa_lsa_originate(route
, area
, true);
1073 /* Loop through the aggregation table to originate type-7 LSAs
1074 * for the aggregated type-5 LSAs
1076 for (rn
= route_top(area
->ospf6
->rt_aggr_tbl
); rn
;
1077 rn
= route_next(rn
)) {
1083 if (CHECK_FLAG(aggr
->aggrflags
,
1084 OSPF6_EXTERNAL_AGGRT_ORIGINATED
)) {
1085 if (IS_OSPF6_DEBUG_NSSA
)
1087 "Originating Type-7 LSAs for area %s",
1090 ospf6_nssa_lsa_originate(aggr
->route
, area
, true);
1096 void ospf6_area_nssa_update(struct ospf6_area
*area
)
1098 if (IS_AREA_NSSA(area
)) {
1099 OSPF6_OPT_CLEAR(area
->options
, OSPF6_OPT_E
);
1100 area
->ospf6
->anyNSSA
++;
1101 OSPF6_OPT_SET(area
->options
, OSPF6_OPT_N
);
1102 area
->NSSATranslatorRole
= OSPF6_NSSA_ROLE_CANDIDATE
;
1103 } else if (IS_AREA_ENABLED(area
)) {
1104 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
1105 zlog_debug("Normal area for if %s", area
->name
);
1106 OSPF6_OPT_CLEAR(area
->options
, OSPF6_OPT_N
);
1107 OSPF6_OPT_SET(area
->options
, OSPF6_OPT_E
);
1108 area
->ospf6
->anyNSSA
--;
1109 area
->NSSATranslatorState
= OSPF6_NSSA_TRANSLATE_DISABLED
;
1112 /* Refresh router LSA */
1113 if (IS_AREA_NSSA(area
)) {
1114 OSPF6_ROUTER_LSA_SCHEDULE(area
);
1116 /* Flush external LSAs. */
1117 ospf6_asbr_remove_externals_from_area(area
);
1119 /* Check if router is ABR */
1120 if (ospf6_check_and_set_router_abr(area
->ospf6
)) {
1121 if (IS_OSPF6_DEBUG_NSSA
)
1122 zlog_debug("Router is ABR area %s", area
->name
);
1123 ospf6_schedule_abr_task(area
->ospf6
);
1125 /* Router is not ABR */
1126 if (IS_OSPF6_DEBUG_NSSA
)
1127 zlog_debug("NSSA area %s", area
->name
);
1129 /* Originate NSSA LSA */
1130 ospf6_check_and_originate_type7_lsa(area
);
1134 if (IS_OSPF6_DEBUG_NSSA
)
1135 zlog_debug("Normal area %s", area
->name
);
1136 ospf6_nssa_flush_area(area
);
1140 int ospf6_area_nssa_set(struct ospf6
*ospf6
, struct ospf6_area
*area
)
1143 if (!IS_AREA_NSSA(area
)) {
1144 /* Disable stub first. */
1145 ospf6_area_stub_unset(ospf6
, area
);
1147 SET_FLAG(area
->flag
, OSPF6_AREA_NSSA
);
1148 if (IS_OSPF6_DEBUG_NSSA
)
1149 zlog_debug("area %s nssa set", area
->name
);
1150 ospf6_area_nssa_update(area
);
1156 int ospf6_area_nssa_unset(struct ospf6
*ospf6
, struct ospf6_area
*area
)
1158 if (IS_AREA_NSSA(area
)) {
1159 UNSET_FLAG(area
->flag
, OSPF6_AREA_NSSA
);
1160 if (IS_OSPF6_DEBUG_NSSA
)
1161 zlog_debug("area %s nssa reset", area
->name
);
1163 /* Clear the table of NSSA ranges. */
1164 ospf6_route_table_delete(area
->nssa_range_table
);
1165 area
->nssa_range_table
=
1166 OSPF6_ROUTE_TABLE_CREATE(AREA
, PREFIX_RANGES
);
1167 area
->nssa_range_table
->scope
= area
;
1169 ospf6_area_nssa_update(area
);
1175 /* Find the NSSA forwarding address */
1176 static struct in6_addr
*ospf6_get_nssa_fwd_addr(struct ospf6_area
*oa
)
1178 struct listnode
*node
, *nnode
;
1179 struct ospf6_interface
*oi
;
1181 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
1182 struct in6_addr
*addr
;
1184 if (!if_is_operative(oi
->interface
))
1187 addr
= ospf6_interface_get_global_address(oi
->interface
);
1194 void ospf6_nssa_lsa_originate(struct ospf6_route
*route
,
1195 struct ospf6_area
*area
, bool p_bit
)
1197 char buffer
[OSPF6_MAX_LSASIZE
];
1198 struct ospf6_lsa_header
*lsa_header
;
1199 struct ospf6_lsa
*lsa
;
1200 struct ospf6_external_info
*info
= route
->route_option
;
1201 struct in6_addr
*fwd_addr
;
1203 struct ospf6_as_external_lsa
*as_external_lsa
;
1206 if (IS_OSPF6_DEBUG_ASBR
|| IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL
))
1207 zlog_debug("Originate NSSA-LSA for %pFX", &route
->prefix
);
1209 /* prepare buffer */
1210 memset(buffer
, 0, sizeof(buffer
));
1211 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1212 as_external_lsa
= (struct ospf6_as_external_lsa
1213 *)((caddr_t
)lsa_header
1214 + sizeof(struct ospf6_lsa_header
));
1215 p
= (caddr_t
)((caddr_t
)as_external_lsa
1216 + sizeof(struct ospf6_as_external_lsa
));
1218 /* Fill AS-External-LSA */
1220 if (route
->path
.metric_type
== 2)
1221 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
1223 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
1225 /* external route tag */
1226 if (info
&& info
->tag
)
1227 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
1229 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
1232 OSPF6_ASBR_METRIC_SET(as_external_lsa
, route
->path
.cost
);
1235 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
1238 as_external_lsa
->prefix
.prefix_options
= route
->prefix_options
;
1242 as_external_lsa
->prefix
.prefix_options
|= OSPF6_PREFIX_OPTION_P
;
1244 /* don't use refer LS-type */
1245 as_external_lsa
->prefix
.prefix_refer_lstype
= htons(0);
1248 memcpy(p
, &route
->prefix
.u
.prefix6
,
1249 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
1250 ospf6_prefix_apply_mask(&as_external_lsa
->prefix
);
1251 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
1253 /* Forwarding address */
1254 fwd_addr
= ospf6_get_nssa_fwd_addr(area
);
1256 memcpy(p
, fwd_addr
, sizeof(struct in6_addr
));
1257 p
+= sizeof(struct in6_addr
);
1258 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
1260 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
1262 /* External Route Tag */
1264 && CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
1265 route_tag_t network_order
= htonl(info
->tag
);
1267 memcpy(p
, &network_order
, sizeof(network_order
));
1268 p
+= sizeof(network_order
);
1271 /* Fill LSA Header */
1272 lsa_header
->age
= 0;
1273 lsa_header
->type
= htons(OSPF6_LSTYPE_TYPE_7
);
1274 lsa_header
->id
= route
->path
.origin
.id
;
1275 lsa_header
->adv_router
= area
->ospf6
->router_id
;
1276 lsa_header
->seqnum
=
1277 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1278 lsa_header
->adv_router
, area
->lsdb
);
1279 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
1282 ospf6_lsa_checksum(lsa_header
);
1284 lsa
= ospf6_lsa_create(lsa_header
);
1287 ospf6_lsa_originate_area(lsa
, area
);
1290 void ospf6_abr_check_translate_nssa(struct ospf6_area
*area
,
1291 struct ospf6_lsa
*lsa
)
1293 struct ospf6_lsa
*type5
= NULL
;
1294 struct ospf6
*ospf6
= area
->ospf6
;
1296 if (IS_OSPF6_DEBUG_NSSA
)
1297 zlog_debug("%s : start", __func__
);
1299 if (!ospf6_check_and_set_router_abr(ospf6
))
1302 type5
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1303 lsa
->external_lsa_id
, ospf6
->router_id
,
1306 if (IS_OSPF6_DEBUG_NSSA
)
1307 zlog_debug("%s : Originating type5 LSA", __func__
);
1308 ospf6_lsa_translated_nssa_new(area
, lsa
);
1312 DEFPY (area_nssa_range
,
1313 area_nssa_range_cmd
,
1314 "area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
1315 "OSPF6 area parameters\n"
1316 "OSPF6 area ID in IP address format\n"
1317 "OSPF6 area ID as a decimal value\n"
1318 "Configure OSPF6 area as nssa\n"
1319 "Configured address range\n"
1320 "Specify IPv6 prefix\n"
1321 "Do not advertise\n"
1322 "User specified metric for this range\n"
1323 "Advertised metric for this range\n")
1325 struct ospf6_area
*oa
;
1326 struct ospf6_route
*range
;
1328 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1330 OSPF6_CMD_AREA_GET(area
, oa
, ospf6
);
1332 if (!IS_AREA_NSSA(oa
)) {
1333 vty_out(vty
, "%% First configure %s as an NSSA area\n", area
);
1337 range
= ospf6_route_lookup((struct prefix
*)prefix
,
1338 oa
->nssa_range_table
);
1339 if (range
== NULL
) {
1340 range
= ospf6_route_create(ospf6
);
1341 range
->type
= OSPF6_DEST_TYPE_RANGE
;
1342 SET_FLAG(range
->flag
, OSPF6_ROUTE_NSSA_RANGE
);
1343 prefix_copy(&range
->prefix
, prefix
);
1344 range
->path
.area_id
= oa
->area_id
;
1345 range
->path
.metric_type
= 2;
1346 range
->path
.cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
1347 range
->path
.origin
.type
= htons(OSPF6_LSTYPE_TYPE_7
);
1348 range
->path
.origin
.id
= htonl(ospf6
->external_id
++);
1349 range
->path
.origin
.adv_router
= ospf6
->router_id
;
1350 ospf6_route_add(range
, oa
->nssa_range_table
);
1353 /* process "not-advertise" */
1355 SET_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
1357 UNSET_FLAG(range
->flag
, OSPF6_ROUTE_DO_NOT_ADVERTISE
);
1359 /* process "cost" */
1361 cost
= OSPF_AREA_RANGE_COST_UNSPEC
;
1362 range
->path
.u
.cost_config
= cost
;
1364 /* Redo summaries if required */
1365 if (ospf6_check_and_set_router_abr(ospf6
))
1366 ospf6_schedule_abr_task(ospf6
);
1371 DEFPY (no_area_nssa_range
,
1372 no_area_nssa_range_cmd
,
1373 "no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
1375 "OSPF6 area parameters\n"
1376 "OSPF6 area ID in IP address format\n"
1377 "OSPF6 area ID as a decimal value\n"
1378 "Configure OSPF6 area as nssa\n"
1379 "Configured address range\n"
1380 "Specify IPv6 prefix\n"
1381 "Do not advertise\n"
1382 "User specified metric for this range\n"
1383 "Advertised metric for this range\n")
1385 struct ospf6_area
*oa
;
1386 struct ospf6_route
*range
;
1388 VTY_DECLVAR_CONTEXT(ospf6
, ospf6
);
1390 OSPF6_CMD_AREA_GET(area
, oa
, ospf6
);
1392 range
= ospf6_route_lookup((struct prefix
*)prefix
,
1393 oa
->nssa_range_table
);
1394 if (range
== NULL
) {
1395 vty_out(vty
, "%% range %s does not exist.\n", prefix_str
);
1399 if (ospf6_check_and_set_router_abr(oa
->ospf6
)) {
1400 /* Blow away the aggregated LSA and route */
1401 SET_FLAG(range
->flag
, OSPF6_ROUTE_REMOVE
);
1403 /* Redo summaries if required */
1404 thread_execute(master
, ospf6_abr_task_timer
, ospf6
, 0);
1407 ospf6_route_remove(range
, oa
->nssa_range_table
);
1412 DEFUN(debug_ospf6_nssa
, debug_ospf6_nssa_cmd
,
1416 "Debug OSPFv3 NSSA function\n")
1418 OSPF6_DEBUG_NSSA_ON();
1422 DEFUN(no_debug_ospf6_nssa
, no_debug_ospf6_nssa_cmd
,
1423 "no debug ospf6 nssa",
1427 "Debug OSPFv3 NSSA function\n")
1429 OSPF6_DEBUG_NSSA_OFF();
1433 void config_write_ospf6_debug_nssa(struct vty
*vty
)
1435 if (IS_OSPF6_DEBUG_NSSA
)
1436 vty_out(vty
, "debug ospf6 nssa\n");
1439 void install_element_ospf6_debug_nssa(void)
1441 install_element(OSPF6_NODE
, &area_nssa_range_cmd
);
1442 install_element(OSPF6_NODE
, &no_area_nssa_range_cmd
);
1444 install_element(ENABLE_NODE
, &debug_ospf6_nssa_cmd
);
1445 install_element(ENABLE_NODE
, &no_debug_ospf6_nssa_cmd
);
1446 install_element(CONFIG_NODE
, &debug_ospf6_nssa_cmd
);
1447 install_element(CONFIG_NODE
, &no_debug_ospf6_nssa_cmd
);