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"
53 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA
, "OSPF6 LSA");
54 unsigned char config_debug_ospf6_nssa
= 0;
55 /* Determine whether this router is elected translator or not for area */
56 static int ospf6_abr_nssa_am_elected(struct ospf6_area
*oa
)
58 struct ospf6_lsa
*lsa
;
59 struct ospf6_router_lsa
*router_lsa
;
60 in_addr_t
*best
= NULL
;
63 type
= htons(OSPF6_LSTYPE_ROUTER
);
65 /* Verify all the router LSA to compare the router ID */
66 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
)) {
68 router_lsa
= (struct ospf6_router_lsa
69 *)((caddr_t
)lsa
->header
70 + sizeof(struct ospf6_lsa_header
));
72 /* ignore non-ABR routers */
73 if (!CHECK_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
))
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
);
85 best
= &lsa
->header
->adv_router
;
86 else if (IPV4_ADDR_CMP(best
, &lsa
->header
->adv_router
) < 0)
87 best
= &lsa
->header
->adv_router
;
91 if (IS_OSPF6_DEBUG_NSSA
)
92 zlog_debug("%s: best electable ABR not found",
97 if (IS_OSPF6_DEBUG_NSSA
)
98 zlog_debug("%s: best electable ABR is: %pI4", __func__
, best
);
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
);
105 if (IS_OSPF6_DEBUG_NSSA
)
106 zlog_debug("%s: not elected best %pI4, router ID %pI4",
107 __func__
, best
, &oa
->ospf6
->router_id
);
112 /* Flush the translated LSA when translation is disabled */
113 static void ospf6_flush_translated_lsa(struct ospf6_area
*area
)
116 struct ospf6_lsa
*type7
;
117 struct ospf6_lsa
*type5
;
118 struct ospf6
*ospf6
= area
->ospf6
;
120 if (IS_OSPF6_DEBUG_NSSA
)
121 zlog_debug("%s: start area %s", __func__
, area
->name
);
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
);
131 if (IS_OSPF6_DEBUG_NSSA
)
132 zlog_debug("%s: finish area %s", __func__
, area
->name
);
135 /* Check NSSA status for all nssa areas*/
136 void ospf6_abr_nssa_check_status(struct ospf6
*ospf6
)
138 struct ospf6_area
*area
;
139 struct listnode
*lnode
, *nnode
;
141 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, lnode
, nnode
, area
)) {
142 uint8_t old_state
= area
->NSSATranslatorState
;
144 if (IS_OSPF6_DEBUG_NSSA
)
145 zlog_debug("%s: checking area %s flag %x", __func__
,
146 area
->name
, area
->flag
);
148 if (!IS_AREA_NSSA(area
))
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
);
159 if (area
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
160 area
->NSSATranslatorState
=
161 OSPF6_NSSA_TRANSLATE_ENABLED
;
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
)
169 "%s: elected translator",
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",
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.
187 if (old_state
!= area
->NSSATranslatorState
) {
188 if (old_state
== OSPF6_NSSA_TRANSLATE_DISABLED
)
189 ospf6_asbr_status_update(ospf6
,
190 ++ospf6
->redist_count
);
192 ospf6_asbr_status_update(ospf6
,
193 --ospf6
->redist_count
);
198 /* Mark the summary LSA's as unapproved, when ABR status changes.*/
199 static void ospf6_abr_unapprove_summaries(struct ospf6
*ospf6
)
201 struct listnode
*node
, *nnode
;
202 struct ospf6_area
*area
;
203 struct ospf6_lsa
*lsa
;
206 if (IS_OSPF6_DEBUG_ABR
)
207 zlog_debug("%s : Start", __func__
);
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__
,
213 /* Inter area router LSA */
214 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
215 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
217 if (IS_OSPF6_DEBUG_ABR
)
219 "%s : approved unset on summary link id %pI4",
220 __func__
, &lsa
->header
->id
);
221 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
223 /* Inter area prefix LSA */
224 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
225 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
227 if (IS_OSPF6_DEBUG_ABR
)
229 "%s : approved unset on asbr-summary link id %pI4",
230 __func__
, &lsa
->header
->id
);
231 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
235 if (IS_OSPF6_DEBUG_ABR
)
236 zlog_debug("%s : Stop", __func__
);
239 /* Re-advertise inter-area router LSA's */
240 void ospf6_asbr_prefix_readvertise(struct ospf6
*ospf6
)
242 struct ospf6_route
*brouter
;
243 struct listnode
*node
, *nnode
;
244 struct ospf6_area
*oa
;
246 if (IS_OSPF6_DEBUG_ABR
)
247 zlog_debug("Re-examining Inter-Router prefixes");
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
);
256 if (IS_OSPF6_DEBUG_ABR
)
257 zlog_debug("Finished re-examining Inter-Router prefixes");
260 /* Advertise prefixes configured using area <area-id> range command */
261 static void ospf6_abr_announce_aggregates(struct ospf6
*ospf6
)
263 struct ospf6_area
*area
;
264 struct ospf6_route
*range
;
265 struct listnode
*node
, *nnode
;
267 if (IS_OSPF6_DEBUG_ABR
)
268 zlog_debug("ospf6_abr_announce_aggregates(): Start");
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
);
276 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, area
)) {
277 if (IS_OSPF6_DEBUG_ABR
)
279 "ospf_abr_announce_aggregates(): looking at area %pI4",
283 if (IS_OSPF6_DEBUG_ABR
)
284 zlog_debug("ospf6_abr_announce_aggregates(): Stop");
287 /* Flush the summary LSA's which are not approved.*/
288 void ospf6_abr_remove_unapproved_summaries(struct ospf6
*ospf6
)
290 struct listnode
*node
, *nnode
;
291 struct ospf6_area
*area
;
292 struct ospf6_lsa
*lsa
;
295 if (IS_OSPF6_DEBUG_ABR
)
296 zlog_debug("%s : Start", __func__
);
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__
,
303 /* Inter area router LSA */
304 type
= htons(OSPF6_LSTYPE_INTER_ROUTER
);
305 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
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
,
315 /* Inter area prefix LSA */
316 type
= htons(OSPF6_LSTYPE_INTER_PREFIX
);
317 for (ALL_LSDB_TYPED_ADVRTR(area
->lsdb
, type
, ospf6
->router_id
,
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
,
328 if (IS_OSPF6_DEBUG_ABR
)
329 zlog_debug("%s : Stop", __func__
);
333 * This is the function taking care about ABR stuff, i.e.
334 * summary-LSA origination and flooding.
336 static void ospf6_abr_task(struct ospf6
*ospf6
)
338 if (IS_OSPF6_DEBUG_ABR
)
339 zlog_debug("%s : Start", __func__
);
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",
348 ospf6_abr_unapprove_summaries(ospf6
);
350 if (IS_OSPF6_DEBUG_ABR
)
351 zlog_debug("%s : prepare aggregates", __func__
);
353 ospf6_abr_range_reset_cost(ospf6
);
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
);
360 if (IS_OSPF6_DEBUG_ABR
)
361 zlog_debug("%s : process router RT", __func__
);
362 ospf6_asbr_prefix_readvertise(ospf6
);
364 if (IS_OSPF6_DEBUG_ABR
)
365 zlog_debug("%s : announce aggregates", __func__
);
366 ospf6_abr_announce_aggregates(ospf6
);
368 if (IS_OSPF6_DEBUG_ABR
)
369 zlog_debug("%s : announce stub defaults", __func__
);
370 ospf6_abr_defaults_to_stub(ospf6
);
373 if (IS_OSPF6_DEBUG_ABR
)
374 zlog_debug("%s : remove unapproved summaries", __func__
);
375 ospf6_abr_remove_unapproved_summaries(ospf6
);
377 if (IS_OSPF6_DEBUG_ABR
)
378 zlog_debug("%s : Stop", __func__
);
381 /* For NSSA Translations
382 * Mark the translated LSA's as unapproved. */
383 static void ospf6_abr_unapprove_translates(struct ospf6
*ospf6
)
385 struct ospf6_lsa
*lsa
;
387 struct ospf6_area
*oa
;
388 struct listnode
*node
;
390 if (IS_OSPF6_DEBUG_NSSA
)
391 zlog_debug("ospf6_abr_unapprove_translates(): Start");
393 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
394 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
395 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
)) {
396 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
397 SET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
398 if (IS_OSPF6_DEBUG_NSSA
)
400 "%s : approved unset on link id %pI4",
401 __func__
, &lsa
->header
->id
);
406 if (IS_OSPF6_DEBUG_NSSA
)
407 zlog_debug("ospf6_abr_unapprove_translates(): Stop");
410 /* Generate the translated external lsa from NSSA lsa */
411 static struct ospf6_lsa
*ospf6_lsa_translated_nssa_new(struct ospf6_area
*area
,
412 struct ospf6_lsa
*type7
)
415 struct ospf6_lsa
*lsa
;
416 struct ospf6_as_external_lsa
*ext
, *extnew
;
417 struct ospf6_lsa_header
*lsa_header
;
418 caddr_t old_ptr
, new_ptr
;
419 struct ospf6_as_external_lsa
*nssa
;
420 struct prefix prefix
;
421 struct ospf6_route
*match
;
422 struct ospf6
*ospf6
= area
->ospf6
;
423 ptrdiff_t tag_offset
= 0;
424 route_tag_t network_order
;
426 if (IS_OSPF6_DEBUG_NSSA
)
427 zlog_debug("%s : Start", __func__
);
429 if (area
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
) {
430 if (IS_OSPF6_DEBUG_NSSA
)
431 zlog_debug("%s: Translation disabled for area %s",
432 __func__
, area
->name
);
436 buffer
= XCALLOC(MTYPE_OSPF6_LSA
, OSPF6_MAX_LSASIZE
);
437 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
438 extnew
= (struct ospf6_as_external_lsa
439 *)((caddr_t
)lsa_header
440 + sizeof(struct ospf6_lsa_header
));
441 ext
= (struct ospf6_as_external_lsa
442 *)((caddr_t
)(type7
->header
)
443 + sizeof(struct ospf6_lsa_header
));
445 (caddr_t
)((caddr_t
)ext
+ sizeof(struct ospf6_as_external_lsa
));
446 new_ptr
= (caddr_t
)((caddr_t
)extnew
447 + sizeof(struct ospf6_as_external_lsa
));
449 memcpy(extnew
, ext
, sizeof(struct ospf6_as_external_lsa
));
451 /* find the translated Type-5 for this Type-7 */
452 nssa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
455 prefix
.family
= AF_INET6
;
456 prefix
.prefixlen
= nssa
->prefix
.prefix_length
;
457 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, nssa
, &nssa
->prefix
);
459 /* Find the LSA from the external route */
460 match
= ospf6_route_lookup(&prefix
, area
->route_table
);
462 if (IS_OSPF6_DEBUG_NSSA
)
463 zlog_debug("%s : no matching route %pFX", __func__
,
469 memcpy(new_ptr
, old_ptr
, OSPF6_PREFIX_SPACE(ext
->prefix
.prefix_length
));
470 ospf6_prefix_apply_mask(&extnew
->prefix
);
471 new_ptr
+= OSPF6_PREFIX_SPACE(extnew
->prefix
.prefix_length
);
474 sizeof(*ext
) + OSPF6_PREFIX_SPACE(ext
->prefix
.prefix_length
);
476 /* Forwarding address */
477 if (CHECK_FLAG(ext
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
478 memcpy(new_ptr
, (caddr_t
)ext
+ tag_offset
,
479 sizeof(struct in6_addr
));
480 new_ptr
+= sizeof(struct in6_addr
);
481 tag_offset
+= sizeof(struct in6_addr
);
483 /* External Route Tag */
484 if (CHECK_FLAG(ext
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
485 memcpy(&network_order
, (caddr_t
)ext
+ tag_offset
,
486 sizeof(network_order
));
487 network_order
= htonl(network_order
);
488 memcpy(new_ptr
, &network_order
, sizeof(network_order
));
489 new_ptr
+= sizeof(network_order
);
492 /* Fill LSA Header */
494 lsa_header
->type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
495 lsa_header
->id
= htonl(ospf6
->external_id
);
496 ospf6
->external_id
++;
497 lsa_header
->adv_router
= ospf6
->router_id
;
499 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
500 lsa_header
->adv_router
, ospf6
->lsdb
);
501 lsa_header
->length
= htons((caddr_t
)new_ptr
- (caddr_t
)lsa_header
);
502 type7
->external_lsa_id
= lsa_header
->id
;
505 ospf6_lsa_checksum(lsa_header
);
508 lsa
= ospf6_lsa_create(lsa_header
);
510 SET_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
);
511 UNSET_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
);
514 ospf6_lsa_originate_process(lsa
, ospf6
);
516 if (IS_OSPF6_DEBUG_NSSA
)
517 zlog_debug("%s: Originated type5 LSA id %pI4", __func__
,
522 /* Delete LSA from retransmission list */
523 static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6
*ospf6
,
524 struct ospf6_lsa
*lsa
)
526 struct listnode
*node
, *nnode
;
527 struct ospf6_area
*area
;
529 if (IS_OSPF6_DEBUG_NSSA
)
530 zlog_debug("%s : start lsa %s", __func__
, lsa
->name
);
532 /*The function ospf6_flood_clear_area removes LSA from
535 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
))
536 ospf6_flood_clear_area(lsa
, area
);
538 if (IS_OSPF6_DEBUG_NSSA
)
539 zlog_debug("%s : finish lsa %s", __func__
, lsa
->name
);
542 /* Refresh translated AS-external-LSA. */
543 struct ospf6_lsa
*ospf6_translated_nssa_refresh(struct ospf6_area
*area
,
544 struct ospf6_lsa
*type7
,
545 struct ospf6_lsa
*type5
)
547 struct ospf6_lsa
*new = NULL
;
548 struct ospf6_as_external_lsa
*ext_lsa
;
549 struct prefix prefix
;
550 struct ospf6
*ospf6
= area
->ospf6
;
552 if (IS_OSPF6_DEBUG_NSSA
)
553 zlog_debug("%s : start area %s", __func__
, area
->name
);
558 /* Find the AS external LSA */
560 if (IS_OSPF6_DEBUG_NSSA
)
562 "%s: No translated Type-5 found for Type-7 with Id %pI4",
563 __func__
, &type7
->header
->id
);
565 /* find the translated Type-5 for this Type-7 */
566 ext_lsa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
569 prefix
.family
= AF_INET6
;
570 prefix
.prefixlen
= ext_lsa
->prefix
.prefix_length
;
571 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, ext_lsa
,
574 /* Find the AS external LSA from Type-7 LSA */
575 if (IS_OSPF6_DEBUG_NSSA
)
576 zlog_debug("%s: try to find external LSA id %d",
577 __func__
, type7
->external_lsa_id
);
578 type5
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
579 type7
->external_lsa_id
,
580 ospf6
->router_id
, ospf6
->lsdb
);
584 if (CHECK_FLAG(type5
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
585 /* Delete LSA from neighbor retransmit-list. */
586 ospf6_ls_retransmit_delete_nbr_as(ospf6
, type5
);
589 ospf6_lsa_premature_aging(type5
);
591 if (IS_OSPF6_DEBUG_NSSA
)
592 zlog_debug("%s: Invalid translated LSA %s",
593 __func__
, type5
->name
);
598 /* create new translated LSA */
599 if (ospf6_lsa_age_current(type7
) != OSPF_LSA_MAXAGE
) {
600 if ((new = ospf6_lsa_translated_nssa_new(area
, type7
))
602 if (IS_OSPF6_DEBUG_NSSA
)
604 "%s: Could not translate Type-7 for %pI4",
605 __func__
, &type7
->header
->id
);
610 if (IS_OSPF6_DEBUG_NSSA
)
611 zlog_debug("%s: finish", __func__
);
616 /* Originate Translated Type-5 for supplied Type-7 NSSA LSA */
617 struct ospf6_lsa
*ospf6_translated_nssa_originate(struct ospf6_area
*oa
,
618 struct ospf6_lsa
*type7
)
620 struct ospf6_lsa
*new;
622 if (ntohs(type7
->header
->type
) != OSPF6_LSTYPE_TYPE_7
)
625 if ((new = ospf6_lsa_translated_nssa_new(oa
, type7
)) == NULL
) {
626 if (IS_OSPF6_DEBUG_NSSA
)
628 "%s : Could not translate Type-7, Id %pI4, to Type-5",
629 __func__
, &type7
->header
->id
);
636 int ospf6_abr_translate_nssa(struct ospf6_area
*area
, struct ospf6_lsa
*lsa
)
638 /* Incoming Type-7 or later aggregated Type-7
640 * LSA is skipped if P-bit is off.
641 * LSA is aggregated if within range.
643 * The Type-7 is translated, Installed/Approved as a Type-5 into
644 * global LSDB, then Flooded through AS
646 * Later, any Unapproved Translated Type-5's are flushed/discarded
649 struct ospf6_lsa
*old
= NULL
, *new = NULL
;
650 struct ospf6_as_external_lsa
*nssa_lsa
;
651 struct prefix prefix
;
652 struct ospf6_route
*match
;
656 nssa_lsa
= (struct ospf6_as_external_lsa
*)OSPF6_LSA_HEADER_END(
659 if (!CHECK_FLAG(nssa_lsa
->prefix
.prefix_options
,
660 OSPF6_PREFIX_OPTION_P
)) {
661 if (IS_OSPF6_DEBUG_NSSA
)
663 "%s : LSA Id %pI4, P-bit off, NO Translation",
664 __func__
, &lsa
->header
->id
);
668 if (IS_OSPF6_DEBUG_NSSA
)
670 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
671 __func__
, &lsa
->header
->id
, &lsa
->external_lsa_id
);
673 prefix
.family
= AF_INET6
;
674 prefix
.prefixlen
= nssa_lsa
->prefix
.prefix_length
;
675 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, nssa_lsa
, &nssa_lsa
->prefix
);
677 if (!CHECK_FLAG(nssa_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
)) {
678 if (IS_OSPF6_DEBUG_NSSA
)
680 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
681 __func__
, &lsa
->header
->id
);
685 /* Find the existing AS-External LSA for this prefix */
686 match
= ospf6_route_lookup(&prefix
, ospf6
->external_table
);
688 old
= ospf6_lsdb_lookup(OSPF6_LSTYPE_AS_EXTERNAL
,
689 match
->path
.origin
.id
, ospf6
->router_id
,
693 /* Check Type 5 LSA using the matching external ID */
695 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
696 lsa
->external_lsa_id
, ospf6
->router_id
,
701 /* Do not continue if type 5 LSA not approved */
702 if (CHECK_FLAG(old
->flag
, OSPF6_LSA_UNAPPROVED
)) {
703 if (IS_OSPF6_DEBUG_NSSA
)
705 "%s : LSA Id %pI4 type 5 is not approved",
706 __func__
, &old
->header
->id
);
710 if (IS_OSPF6_DEBUG_NSSA
)
712 "%s : found old translated LSA Id %pI4, refreshing",
713 __func__
, &old
->header
->id
);
716 new = ospf6_translated_nssa_refresh(area
, lsa
, old
);
718 if (IS_OSPF6_DEBUG_NSSA
)
720 "%s : could not refresh translated LSA Id %pI4",
721 __func__
, &old
->header
->id
);
724 /* no existing external route for this LSA Id
725 * originate translated LSA
728 if (ospf6_translated_nssa_originate(area
, lsa
) == NULL
) {
729 if (IS_OSPF6_DEBUG_NSSA
)
731 "%s : Could not translate Type-7 for %pI4 to Type-5",
732 __func__
, &lsa
->header
->id
);
740 static void ospf6_abr_process_nssa_translates(struct ospf6
*ospf6
)
742 /* Scan through all NSSA_LSDB records for all areas;
743 * If P-bit is on, translate all Type-7's to 5's and aggregate or\
744 * flood install as approved in Type-5 LSDB with XLATE Flag on
745 * later, do same for all aggregates... At end, DISCARD all
746 * remaining UNAPPROVED Type-5's (Aggregate is for future ) */
748 struct listnode
*node
;
749 struct ospf6_area
*oa
;
750 struct ospf6_lsa
*lsa
;
753 if (IS_OSPF6_DEBUG_NSSA
)
754 zlog_debug("%s : Start", __func__
);
756 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
758 /* skip if not translator */
759 if (oa
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
) {
760 zlog_debug("%s area %pI4 NSSATranslatorState %d",
761 __func__
, &oa
->area_id
,
762 oa
->NSSATranslatorState
);
766 /* skip if not Nssa Area */
767 if (!IS_AREA_NSSA(oa
)) {
768 zlog_debug("%s area %pI4 Flag %x", __func__
,
769 &oa
->area_id
, oa
->flag
);
773 if (IS_OSPF6_DEBUG_NSSA
)
774 zlog_debug("%s : looking at area %pI4", __func__
,
777 type
= htons(OSPF6_LSTYPE_TYPE_7
);
778 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
)) {
779 zlog_debug("%s : lsa %s , id %pI4 , adv router %pI4",
780 lsa
->name
, __func__
, &lsa
->header
->id
,
781 &lsa
->header
->adv_router
);
782 ospf6_abr_translate_nssa(oa
, lsa
);
786 if (IS_OSPF6_DEBUG_NSSA
)
787 zlog_debug("%s : Stop", __func__
);
790 /* Generate translated type-5 LSA from the configured area ranges*/
791 static void ospf6_abr_translate_nssa_range(struct ospf6
*ospf6
)
793 struct listnode
*node
, *nnode
;
794 struct ospf6_area
*oa
;
795 struct ospf6_route
*range
;
796 struct ospf6_lsa
*lsa
;
798 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, oa
)) {
799 for (range
= ospf6_route_head(oa
->range_table
); range
;
800 range
= ospf6_route_next(range
)) {
801 if (IS_OSPF6_DEBUG_NSSA
)
803 "Translating range %pFX of area %pI4",
804 &range
->prefix
, &oa
->area_id
);
805 if (CHECK_FLAG(range
->flag
,
806 OSPF6_ROUTE_DO_NOT_ADVERTISE
))
809 /* Find the NSSA LSA from the route */
810 /* Generate and flood external LSA */
811 lsa
= ospf6_lsdb_lookup(OSPF6_LSTYPE_TYPE_7
,
812 range
->path
.origin
.id
,
813 ospf6
->router_id
, oa
->lsdb
);
815 ospf6_abr_translate_nssa(oa
, lsa
);
820 static void ospf6_abr_send_nssa_aggregates(struct ospf6
*ospf6
)
822 struct listnode
*node
;
823 struct ospf6_area
*area
;
825 if (IS_OSPF6_DEBUG_NSSA
)
826 zlog_debug("%s : Start", __func__
);
828 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, area
)) {
829 if (area
->NSSATranslatorState
== OSPF6_NSSA_TRANSLATE_DISABLED
)
832 if (IS_OSPF6_DEBUG_NSSA
)
833 zlog_debug("%s : looking at area %pI4", __func__
,
836 ospf6_abr_translate_nssa_range(ospf6
);
839 if (IS_OSPF6_DEBUG_NSSA
)
840 zlog_debug("%s : Stop", __func__
);
843 /*Flood max age LSA's for the unapproved LSA's */
844 static int ospf6_abr_remove_unapproved_translates_apply(struct ospf6_lsa
*lsa
)
846 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_LOCAL_XLT
)
847 && CHECK_FLAG(lsa
->flag
, OSPF6_LSA_UNAPPROVED
)) {
848 zlog_debug("%s : removing unapproved translates, lsa : %s",
849 __func__
, lsa
->name
);
851 /* FLUSH THROUGHOUT AS */
852 ospf6_lsa_premature_aging(lsa
);
857 static void ospf6_abr_remove_unapproved_translates(struct ospf6
*ospf6
)
859 struct ospf6_lsa
*lsa
;
862 /* All AREA PROCESS should have APPROVED necessary LSAs */
863 /* Remove any left over and not APPROVED */
864 if (IS_OSPF6_DEBUG_NSSA
)
865 zlog_debug("ospf6_abr_remove_unapproved_translates(): Start");
867 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
868 for (ALL_LSDB_TYPED(ospf6
->lsdb
, type
, lsa
))
869 ospf6_abr_remove_unapproved_translates_apply(lsa
);
871 if (IS_OSPF6_DEBUG_NSSA
)
872 zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
875 static void ospf6_abr_nssa_task(struct ospf6
*ospf6
)
877 /* called only if any_nssa */
878 struct ospf6_route
*range
;
879 struct ospf6_area
*area
;
880 struct listnode
*node
, *nnode
;
882 if (IS_OSPF6_DEBUG_NSSA
)
883 zlog_debug("Check for NSSA-ABR Tasks():");
885 if (!IS_OSPF6_ABR(ospf6
)) {
886 if (IS_OSPF6_DEBUG_NSSA
)
887 zlog_debug("%s Not ABR", __func__
);
891 if (!ospf6
->anyNSSA
) {
892 if (IS_OSPF6_DEBUG_NSSA
)
893 zlog_debug("%s Not NSSA", __func__
);
897 /* Each area must confirm TranslatorRole */
898 if (IS_OSPF6_DEBUG_NSSA
)
899 zlog_debug("ospf6_abr_nssa_task(): Start");
901 /* For all Global Entries flagged "local-translate", unset APPROVED */
902 if (IS_OSPF6_DEBUG_NSSA
)
903 zlog_debug("ospf6_abr_nssa_task(): unapprove translates");
905 ospf6_abr_unapprove_translates(ospf6
);
907 /* RESET all Ranges in every Area, same as summaries */
908 if (IS_OSPF6_DEBUG_NSSA
)
909 zlog_debug("ospf6_abr_nssa_task(): NSSA initialize aggregates");
910 ospf6_abr_range_reset_cost(ospf6
);
912 /* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
913 * Aggregate as Type-7
914 * Install or Approve in Type-5 Global LSDB
916 if (IS_OSPF6_DEBUG_NSSA
)
917 zlog_debug("ospf6_abr_nssa_task(): process translates");
918 ospf6_abr_process_nssa_translates(ospf6
);
920 /* Translate/Send any "ranged" aggregates, and also 5-Install and
922 * Scan Type-7's for aggregates, translate to Type-5's,
923 * Install/Flood/Approve
925 if (IS_OSPF6_DEBUG_NSSA
)
926 zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
927 ospf6_abr_send_nssa_aggregates(ospf6
); /*TURNED OFF FOR NOW */
929 /* Flush any unapproved previous translates from Global Data Base */
930 if (IS_OSPF6_DEBUG_NSSA
)
932 "ospf6_abr_nssa_task(): remove unapproved translates");
933 ospf6_abr_remove_unapproved_translates(ospf6
);
935 for (ALL_LIST_ELEMENTS(ospf6
->area_list
, node
, nnode
, area
)) {
936 for (range
= ospf6_route_head(area
->range_table
); range
;
937 range
= ospf6_route_next(range
)) {
938 if (CHECK_FLAG(range
->flag
,
939 OSPF6_ROUTE_DO_NOT_ADVERTISE
))
940 ospf6_zebra_delete_discard(range
, ospf6
);
942 ospf6_zebra_add_discard(range
, ospf6
);
946 if (IS_OSPF6_DEBUG_NSSA
)
947 zlog_debug("ospf6_abr_nssa_task(): Stop");
950 int ospf6_redistribute_check(struct ospf6
*ospf6
, struct ospf6_route
*route
,
953 route_map_result_t ret
;
954 struct prefix
*prefix
;
955 struct ospf6_redist
*red
;
957 if (!ospf6_zebra_is_redistribute(type
, ospf6
->vrf_id
))
960 prefix
= &route
->prefix
;
962 red
= ospf6_redist_lookup(ospf6
, type
, 0);
966 /* Change to new redist structure */
967 if (ROUTEMAP_NAME(red
)) {
968 if (ROUTEMAP(red
) == NULL
)
969 ospf6_asbr_routemap_update(NULL
);
970 if (ROUTEMAP(red
) == NULL
) {
972 "route-map \"%s\" not found, suppress redistributing",
978 /* Change to new redist structure */
980 ret
= route_map_apply(ROUTEMAP(red
), prefix
, route
);
981 if (ret
== RMAP_DENYMATCH
) {
982 if (IS_OSPF6_DEBUG_ASBR
)
983 zlog_debug("Denied by route-map \"%s\"",
992 static void ospf6_external_lsa_refresh_type(struct ospf6
*ospf6
, uint8_t type
,
993 unsigned short instance
, int force
)
995 struct ospf6_route
*route
;
996 struct ospf6_external_info
*info
;
997 struct ospf6_lsa
*lsa
;
999 if (type
== ZEBRA_ROUTE_MAX
)
1002 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1003 route
= ospf6_route_next(route
)) {
1004 info
= route
->route_option
;
1006 /* Find the external LSA in the database */
1007 if (!is_default_prefix(&route
->prefix
)) {
1008 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1010 ospf6
->router_id
, ospf6
->lsdb
);
1013 THREAD_OFF(lsa
->refresh
);
1015 /* LSA is maxage, immediate refresh */
1016 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1017 ospf6_flood(NULL
, lsa
);
1019 thread_add_timer(master
,
1020 ospf6_lsa_refresh
, lsa
,
1021 OSPF_LS_REFRESH_TIME
,
1024 /* LSA not found in the database
1025 * Verify and originate external LSA
1027 if (ospf6_redistribute_check(ospf6
, route
,
1029 ospf6_as_external_lsa_originate(route
,
1036 /* Refresh default route */
1037 static void ospf6_external_lsa_refresh_default(struct ospf6
*ospf6
)
1039 struct ospf6_route
*route
;
1040 struct ospf6_external_info
*info
;
1041 struct ospf6_lsa
*lsa
;
1043 for (route
= ospf6_route_head(ospf6
->external_table
); route
;
1044 route
= ospf6_route_next(route
)) {
1045 if (is_default_prefix(&route
->prefix
)) {
1046 info
= route
->route_option
;
1047 lsa
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1049 ospf6
->router_id
, ospf6
->lsdb
);
1052 if (IS_OSPF6_DEBUG_NSSA
)
1054 "LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p",
1056 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1057 ospf6_flood(NULL
, lsa
);
1059 thread_add_timer(master
,
1060 ospf6_lsa_refresh
, lsa
,
1061 OSPF_LS_REFRESH_TIME
,
1064 if (IS_OSPF6_DEBUG_NSSA
)
1066 "LSA[Type5:0.0.0.0]: Originate AS-external-LSA");
1067 ospf6_as_external_lsa_originate(route
, ospf6
);
1073 /* If there's redistribution configured, we need to refresh external
1074 * LSAs in order to install Type-7 and flood to all NSSA Areas
1076 void ospf6_asbr_nssa_redist_task(struct ospf6
*ospf6
)
1079 struct ospf6_redist
*red
;
1081 for (type
= 0; type
< ZEBRA_ROUTE_MAX
; type
++) {
1082 red
= ospf6_redist_lookup(ospf6
, type
, 0);
1086 ospf6_external_lsa_refresh_type(ospf6
, type
, red
->instance
,
1087 LSA_REFRESH_IF_CHANGED
);
1089 ospf6_external_lsa_refresh_default(ospf6
);
1092 /* This function performs ABR related processing */
1093 static int ospf6_abr_task_timer(struct thread
*thread
)
1095 struct ospf6
*ospf6
= THREAD_ARG(thread
);
1097 ospf6
->t_abr_task
= NULL
;
1099 if (IS_OSPF6_DEBUG_ABR
)
1100 zlog_debug("Running ABR task on timer");
1102 (void)ospf6_check_and_set_router_abr(ospf6
);
1103 ospf6_abr_nssa_check_status(ospf6
);
1104 ospf6_abr_task(ospf6
);
1105 /* if nssa-abr, then scan Type-7 LSDB */
1106 ospf6_abr_nssa_task(ospf6
);
1107 ospf6_asbr_nssa_redist_task(ospf6
);
1112 void ospf6_schedule_abr_task(struct ospf6
*ospf6
)
1114 if (ospf6
->t_abr_task
) {
1115 if (IS_OSPF6_DEBUG_ABR
)
1116 zlog_debug("ABR task already scheduled");
1120 if (IS_OSPF6_DEBUG_ABR
)
1121 zlog_debug("Scheduling ABR task");
1123 thread_add_timer(master
, ospf6_abr_task_timer
, ospf6
,
1124 OSPF6_ABR_TASK_DELAY
, &ospf6
->t_abr_task
);
1127 /* Flush the NSSA LSAs from the area */
1128 static void ospf6_nssa_flush_area(struct ospf6_area
*area
)
1131 struct ospf6_lsa
*lsa
= NULL
, *type5
= NULL
;
1132 struct ospf6
*ospf6
= area
->ospf6
;
1133 const struct route_node
*rt
= NULL
;
1135 if (IS_OSPF6_DEBUG_NSSA
)
1136 zlog_debug("%s: area %s", __func__
, area
->name
);
1138 /* Flush the NSSA LSA */
1139 type
= htons(OSPF6_LSTYPE_TYPE_7
);
1140 rt
= ospf6_lsdb_head(area
->lsdb_self
, 0, type
, ospf6
->router_id
, &lsa
);
1142 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
1143 SET_FLAG(lsa
->flag
, OSPF6_LSA_FLUSH
);
1144 ospf6_flood(NULL
, lsa
);
1145 /* Flush the translated LSA */
1146 if (ospf6_check_and_set_router_abr(ospf6
)) {
1147 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
1148 type5
= ospf6_lsdb_lookup(
1149 htons(type
), lsa
->external_lsa_id
,
1150 ospf6
->router_id
, ospf6
->lsdb
);
1152 && CHECK_FLAG(type5
->flag
, OSPF6_LSA_LOCAL_XLT
)) {
1153 type5
->header
->age
= htons(OSPF_LSA_MAXAGE
);
1154 SET_FLAG(type5
->flag
, OSPF6_LSA_FLUSH
);
1155 ospf6_flood(NULL
, type5
);
1158 lsa
= ospf6_lsdb_next(rt
, lsa
);
1162 static void ospf6_area_nssa_update(struct ospf6_area
*area
)
1164 struct ospf6_route
*route
;
1166 if (IS_AREA_NSSA(area
)) {
1167 if (!ospf6_check_and_set_router_abr(area
->ospf6
))
1168 OSPF6_OPT_CLEAR(area
->options
, OSPF6_OPT_E
);
1169 area
->ospf6
->anyNSSA
++;
1170 OSPF6_OPT_SET(area
->options
, OSPF6_OPT_N
);
1171 area
->NSSATranslatorRole
= OSPF6_NSSA_ROLE_CANDIDATE
;
1172 } else if (IS_AREA_ENABLED(area
)) {
1173 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
1174 zlog_debug("Normal area for if %s", area
->name
);
1175 OSPF6_OPT_CLEAR(area
->options
, OSPF6_OPT_N
);
1176 if (ospf6_check_and_set_router_abr(area
->ospf6
))
1177 OSPF6_OPT_SET(area
->options
, OSPF6_OPT_E
);
1178 area
->ospf6
->anyNSSA
--;
1179 area
->NSSATranslatorState
= OSPF6_NSSA_TRANSLATE_DISABLED
;
1182 /* Refresh router LSA */
1183 if (IS_AREA_NSSA(area
)) {
1184 OSPF6_ROUTER_LSA_SCHEDULE(area
);
1186 /* Check if router is ABR */
1187 if (ospf6_check_and_set_router_abr(area
->ospf6
)) {
1188 if (IS_OSPF6_DEBUG_NSSA
)
1189 zlog_debug("Router is ABR area %s", area
->name
);
1190 ospf6_schedule_abr_task(area
->ospf6
);
1192 /* Router is not ABR */
1193 if (IS_OSPF6_DEBUG_NSSA
)
1194 zlog_debug("NSSA area %s", area
->name
);
1196 /* Originate NSSA LSA */
1197 for (route
= ospf6_route_head(
1198 area
->ospf6
->external_table
);
1199 route
; route
= ospf6_route_next(route
))
1200 ospf6_nssa_lsa_originate(route
, area
);
1204 if (IS_OSPF6_DEBUG_NSSA
)
1205 zlog_debug("Normal area %s", area
->name
);
1206 ospf6_nssa_flush_area(area
);
1207 ospf6_area_disable(area
);
1208 ospf6_area_delete(area
);
1212 int ospf6_area_nssa_set(struct ospf6
*ospf6
, struct ospf6_area
*area
)
1215 if (!IS_AREA_NSSA(area
)) {
1216 SET_FLAG(area
->flag
, OSPF6_AREA_NSSA
);
1217 if (IS_OSPF6_DEBUG_NSSA
)
1218 zlog_debug("area %s nssa set", area
->name
);
1219 ospf6_area_nssa_update(area
);
1225 int ospf6_area_nssa_unset(struct ospf6
*ospf6
, struct ospf6_area
*area
)
1227 if (IS_AREA_NSSA(area
)) {
1228 UNSET_FLAG(area
->flag
, OSPF6_AREA_NSSA
);
1229 if (IS_OSPF6_DEBUG_NSSA
)
1230 zlog_debug("area %s nssa reset", area
->name
);
1231 ospf6_area_nssa_update(area
);
1237 /* Find the NSSA forwarding address */
1238 static struct in6_addr
*ospf6_get_nssa_fwd_addr(struct ospf6_area
*oa
)
1240 struct listnode
*node
, *nnode
;
1241 struct ospf6_interface
*oi
;
1243 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
1244 if (if_is_operative(oi
->interface
))
1245 if (oi
->area
&& IS_AREA_NSSA(oi
->area
))
1246 return ospf6_interface_get_global_address(
1252 void ospf6_nssa_lsa_originate(struct ospf6_route
*route
,
1253 struct ospf6_area
*area
)
1255 char buffer
[OSPF6_MAX_LSASIZE
];
1256 struct ospf6_lsa_header
*lsa_header
;
1257 struct ospf6_lsa
*lsa
;
1258 struct ospf6_external_info
*info
= route
->route_option
;
1259 struct in6_addr
*fwd_addr
;
1261 struct ospf6_as_external_lsa
*as_external_lsa
;
1262 char buf
[PREFIX2STR_BUFFER
];
1265 if (IS_OSPF6_DEBUG_ASBR
|| IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL
)) {
1266 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1267 zlog_debug("Originate AS-External-LSA for %s", buf
);
1270 /* prepare buffer */
1271 memset(buffer
, 0, sizeof(buffer
));
1272 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1273 as_external_lsa
= (struct ospf6_as_external_lsa
1274 *)((caddr_t
)lsa_header
1275 + sizeof(struct ospf6_lsa_header
));
1276 p
= (caddr_t
)((caddr_t
)as_external_lsa
1277 + sizeof(struct ospf6_as_external_lsa
));
1279 /* Fill AS-External-LSA */
1281 if (route
->path
.metric_type
== OSPF6_PATH_TYPE_EXTERNAL2
)
1282 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
1284 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_E
);
1286 /* external route tag */
1288 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
1290 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
);
1293 OSPF6_ASBR_METRIC_SET(as_external_lsa
, route
->path
.cost
);
1296 as_external_lsa
->prefix
.prefix_length
= route
->prefix
.prefixlen
;
1299 as_external_lsa
->prefix
.prefix_options
= route
->path
.prefix_options
;
1302 as_external_lsa
->prefix
.prefix_options
|= OSPF6_PREFIX_OPTION_P
;
1304 /* don't use refer LS-type */
1305 as_external_lsa
->prefix
.prefix_refer_lstype
= htons(0);
1308 memcpy(p
, &route
->prefix
.u
.prefix6
,
1309 OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
));
1310 ospf6_prefix_apply_mask(&as_external_lsa
->prefix
);
1311 p
+= OSPF6_PREFIX_SPACE(route
->prefix
.prefixlen
);
1313 /* Forwarding address */
1314 fwd_addr
= ospf6_get_nssa_fwd_addr(area
);
1316 memcpy(p
, fwd_addr
, sizeof(struct in6_addr
));
1317 p
+= sizeof(struct in6_addr
);
1318 SET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
1320 UNSET_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_F
);
1322 /* External Route Tag */
1323 if (CHECK_FLAG(as_external_lsa
->bits_metric
, OSPF6_ASBR_BIT_T
)) {
1324 route_tag_t network_order
= htonl(info
->tag
);
1326 memcpy(p
, &network_order
, sizeof(network_order
));
1327 p
+= sizeof(network_order
);
1330 /* Fill LSA Header */
1331 lsa_header
->age
= 0;
1332 lsa_header
->type
= htons(OSPF6_LSTYPE_TYPE_7
);
1333 lsa_header
->id
= route
->path
.origin
.id
;
1334 lsa_header
->adv_router
= area
->ospf6
->router_id
;
1335 lsa_header
->seqnum
=
1336 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1337 lsa_header
->adv_router
, area
->ospf6
->lsdb
);
1338 lsa_header
->length
= htons((caddr_t
)p
- (caddr_t
)lsa_header
);
1341 ospf6_lsa_checksum(lsa_header
);
1343 lsa
= ospf6_lsa_create(lsa_header
);
1346 ospf6_lsa_originate_area(lsa
, area
);
1349 void ospf6_abr_check_translate_nssa(struct ospf6_area
*area
,
1350 struct ospf6_lsa
*lsa
)
1352 struct ospf6_lsa
*type5
= NULL
;
1353 struct ospf6
*ospf6
= area
->ospf6
;
1355 if (IS_OSPF6_DEBUG_NSSA
)
1356 zlog_debug("%s : start", __func__
);
1358 type5
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL
),
1359 lsa
->external_lsa_id
, ospf6
->router_id
,
1362 if (ospf6_check_and_set_router_abr(ospf6
) && (type5
== NULL
)) {
1363 if (IS_OSPF6_DEBUG_NSSA
)
1364 zlog_debug("%s : Originating type5 LSA", __func__
);
1365 ospf6_lsa_translated_nssa_new(area
, lsa
);
1369 DEFUN(debug_ospf6_nssa
, debug_ospf6_nssa_cmd
,
1373 "Debug OSPFv3 NSSA function\n")
1375 OSPF6_DEBUG_NSSA_ON();
1379 DEFUN(no_debug_ospf6_nssa
, no_debug_ospf6_nssa_cmd
,
1380 "no debug ospf6 nssa",
1384 "Debug OSPFv3 NSSA function\n")
1386 OSPF6_DEBUG_NSSA_OFF();
1390 void config_write_ospf6_debug_nssa(struct vty
*vty
)
1392 if (IS_OSPF6_DEBUG_NSSA
)
1393 vty_out(vty
, "debug ospf6 nssa\n");
1396 void install_element_ospf6_debug_nssa(void)
1398 install_element(ENABLE_NODE
, &debug_ospf6_nssa_cmd
);
1399 install_element(ENABLE_NODE
, &no_debug_ospf6_nssa_cmd
);
1400 install_element(CONFIG_NODE
, &debug_ospf6_nssa_cmd
);
1401 install_element(CONFIG_NODE
, &no_debug_ospf6_nssa_cmd
);