]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_nssa.c
build, vtysh: extract vtysh commands from .xref
[mirror_frr.git] / ospf6d / ospf6_nssa.c
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 #include "ospf6d/ospf6_nssa_clippy.c"
53
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)
58 {
59 struct ospf6_lsa *lsa;
60 struct ospf6_router_lsa *router_lsa;
61 in_addr_t *best = NULL;
62 uint16_t type;
63
64 type = htons(OSPF6_LSTYPE_ROUTER);
65
66 /* Verify all the router LSA to compare the router ID */
67 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
68
69 router_lsa = (struct ospf6_router_lsa
70 *)((caddr_t)lsa->header
71 + sizeof(struct ospf6_lsa_header));
72
73 /* ignore non-ABR routers */
74 if (!CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B))
75 continue;
76
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);
82 return 1;
83 }
84
85 if (best == NULL)
86 best = &lsa->header->adv_router;
87 else if (IPV4_ADDR_CMP(best, &lsa->header->adv_router) < 0)
88 best = &lsa->header->adv_router;
89 }
90
91 if (best == NULL) {
92 if (IS_OSPF6_DEBUG_NSSA)
93 zlog_debug("%s: best electable ABR not found",
94 __func__);
95 return 0;
96 }
97
98 if (IS_OSPF6_DEBUG_NSSA)
99 zlog_debug("%s: best electable ABR is: %pI4", __func__, best);
100
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);
104 return 1;
105 } else {
106 if (IS_OSPF6_DEBUG_NSSA)
107 zlog_debug("%s: not elected best %pI4, router ID %pI4",
108 __func__, best, &oa->ospf6->router_id);
109 return 0;
110 }
111 }
112
113 /* Flush the translated LSA when translation is disabled */
114 static void ospf6_flush_translated_lsa(struct ospf6_area *area)
115 {
116 uint16_t type;
117 struct ospf6_lsa *type7;
118 struct ospf6_lsa *type5;
119 struct ospf6 *ospf6 = area->ospf6;
120
121 if (IS_OSPF6_DEBUG_NSSA)
122 zlog_debug("%s: start area %s", __func__, area->name);
123
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);
131 }
132 if (IS_OSPF6_DEBUG_NSSA)
133 zlog_debug("%s: finish area %s", __func__, area->name);
134 }
135
136 /* Check NSSA status for all nssa areas */
137 void ospf6_abr_nssa_check_status(struct ospf6 *ospf6)
138 {
139 struct ospf6_area *area;
140 struct listnode *lnode, *nnode;
141
142 for (ALL_LIST_ELEMENTS(ospf6->area_list, lnode, nnode, area)) {
143 uint8_t old_state = area->NSSATranslatorState;
144
145 if (IS_OSPF6_DEBUG_NSSA)
146 zlog_debug("%s: checking area %s flag %x", __func__,
147 area->name, area->flag);
148
149 if (!IS_AREA_NSSA(area))
150 continue;
151
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);
158 } else {
159 /* Router is ABR */
160 if (area->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
161 area->NSSATranslatorState =
162 OSPF6_NSSA_TRANSLATE_ENABLED;
163 else {
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)
169 zlog_debug(
170 "%s: elected translator",
171 __func__);
172 } else {
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",
178 __func__);
179 }
180 }
181 }
182
183 /* RFC3101, 3.1:
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.
187 */
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);
193 } else {
194 --ospf6->redist_count;
195 ospf6_asbr_status_update(ospf6,
196 ospf6->redist_count);
197 }
198 }
199 }
200 }
201
202 /* Mark the summary LSA's as unapproved, when ABR status changes.*/
203 static void ospf6_abr_unapprove_summaries(struct ospf6 *ospf6)
204 {
205 struct listnode *node, *nnode;
206 struct ospf6_area *area;
207 struct ospf6_lsa *lsa;
208 uint16_t type;
209
210 if (IS_OSPF6_DEBUG_ABR)
211 zlog_debug("%s : Start", __func__);
212
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__,
216 &area->area_id);
217 /* Inter area router LSA */
218 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
219 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
220 lsa)) {
221 if (IS_OSPF6_DEBUG_ABR)
222 zlog_debug(
223 "%s : approved unset on summary link id %pI4",
224 __func__, &lsa->header->id);
225 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
226 }
227 /* Inter area prefix LSA */
228 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
229 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
230 lsa)) {
231 if (IS_OSPF6_DEBUG_ABR)
232 zlog_debug(
233 "%s : approved unset on asbr-summary link id %pI4",
234 __func__, &lsa->header->id);
235 SET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
236 }
237 }
238
239 if (IS_OSPF6_DEBUG_ABR)
240 zlog_debug("%s : Stop", __func__);
241 }
242
243 /* Re-advertise inter-area router LSA's */
244 void ospf6_asbr_prefix_readvertise(struct ospf6 *ospf6)
245 {
246 struct ospf6_route *brouter;
247 struct listnode *node, *nnode;
248 struct ospf6_area *oa;
249
250 if (IS_OSPF6_DEBUG_ABR)
251 zlog_debug("Re-examining Inter-Router prefixes");
252
253
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);
258 }
259
260 if (IS_OSPF6_DEBUG_ABR)
261 zlog_debug("Finished re-examining Inter-Router prefixes");
262 }
263
264 /* Advertise prefixes configured using area <area-id> range command */
265 static void ospf6_abr_announce_aggregates(struct ospf6 *ospf6)
266 {
267 struct ospf6_area *area;
268 struct ospf6_route *range;
269 struct listnode *node;
270
271 if (IS_OSPF6_DEBUG_ABR)
272 zlog_debug("%s: Start", __func__);
273
274 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
275 if (IS_OSPF6_DEBUG_ABR)
276 zlog_debug(
277 "ospf_abr_announce_aggregates(): looking at area %pI4",
278 &area->area_id);
279
280 for (range = ospf6_route_head(area->range_table); range;
281 range = ospf6_route_next(range))
282 ospf6_abr_range_update(range, ospf6);
283 }
284
285 if (IS_OSPF6_DEBUG_ABR)
286 zlog_debug("%s: Stop", __func__);
287 }
288
289 /* Flush the summary LSA's which are not approved.*/
290 void ospf6_abr_remove_unapproved_summaries(struct ospf6 *ospf6)
291 {
292 struct listnode *node, *nnode;
293 struct ospf6_area *area;
294 struct ospf6_lsa *lsa;
295 uint16_t type;
296
297 if (IS_OSPF6_DEBUG_ABR)
298 zlog_debug("%s : Start", __func__);
299
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__,
303 &area->area_id);
304
305 /* Inter area router LSA */
306 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
307 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
308 lsa)) {
309 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
310 ospf6_lsa_premature_aging(lsa);
311 }
312
313 /* Inter area prefix LSA */
314 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
315 for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id,
316 lsa)) {
317 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED))
318 ospf6_lsa_premature_aging(lsa);
319 }
320 }
321
322 if (IS_OSPF6_DEBUG_ABR)
323 zlog_debug("%s : Stop", __func__);
324 }
325
326 /*
327 * This is the function taking care about ABR stuff, i.e.
328 * summary-LSA origination and flooding.
329 */
330 static void ospf6_abr_task(struct ospf6 *ospf6)
331 {
332 if (IS_OSPF6_DEBUG_ABR)
333 zlog_debug("%s : Start", __func__);
334
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",
338 __func__);
339 return;
340 }
341
342 ospf6_abr_unapprove_summaries(ospf6);
343
344 if (IS_OSPF6_DEBUG_ABR)
345 zlog_debug("%s : prepare aggregates", __func__);
346
347 ospf6_abr_range_reset_cost(ospf6);
348
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);
353
354 if (IS_OSPF6_DEBUG_ABR)
355 zlog_debug("%s : process router RT", __func__);
356 ospf6_asbr_prefix_readvertise(ospf6);
357
358 if (IS_OSPF6_DEBUG_ABR)
359 zlog_debug("%s : announce aggregates", __func__);
360 ospf6_abr_announce_aggregates(ospf6);
361
362 if (IS_OSPF6_DEBUG_ABR)
363 zlog_debug("%s : announce stub defaults", __func__);
364 ospf6_abr_defaults_to_stub(ospf6);
365
366 if (IS_OSPF6_DEBUG_ABR)
367 zlog_debug("%s : announce NSSA Type-7 defaults",
368 __func__);
369 ospf6_abr_nssa_type_7_defaults(ospf6);
370 }
371
372 if (IS_OSPF6_DEBUG_ABR)
373 zlog_debug("%s : remove unapproved summaries", __func__);
374 ospf6_abr_remove_unapproved_summaries(ospf6);
375
376 if (IS_OSPF6_DEBUG_ABR)
377 zlog_debug("%s : Stop", __func__);
378 }
379
380 /* For NSSA Translations
381 * Mark the translated LSA's as unapproved. */
382 static void ospf6_abr_unapprove_translates(struct ospf6 *ospf6)
383 {
384 struct ospf6_lsa *lsa;
385 uint16_t type;
386
387 if (IS_OSPF6_DEBUG_NSSA)
388 zlog_debug("%s: Start", __func__);
389
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)
395 zlog_debug(
396 "%s : approved unset on link id %pI4",
397 __func__, &lsa->header->id);
398 }
399 }
400
401 if (IS_OSPF6_DEBUG_NSSA)
402 zlog_debug("%s: Stop", __func__);
403 }
404
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)
408 {
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;
420
421 if (IS_OSPF6_DEBUG_NSSA)
422 zlog_debug("%s : Start", __func__);
423
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);
428 return NULL;
429 }
430
431 /* find the translated Type-5 for this Type-7 */
432 nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
433 type7->header);
434 prefix.family = AF_INET6;
435 prefix.prefixlen = nssa->prefix.prefix_length;
436 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
437
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)
443 zlog_debug(
444 "%s: LSA %s suppressed by range %pFX of area %s",
445 __func__, type7->name, &range->prefix,
446 area->name);
447 return NULL;
448 }
449
450 /* prepare buffer */
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));
459 old_ptr =
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));
463
464 memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
465
466 /* set Prefix */
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);
470
471 tag_offset =
472 sizeof(*ext) + OSPF6_PREFIX_SPACE(ext->prefix.prefix_length);
473
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);
480 }
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);
488 }
489
490 /* Fill LSA Header */
491 lsa_header->age = 0;
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;
496 lsa_header->seqnum =
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;
501
502 /* LSA checksum */
503 ospf6_lsa_checksum(lsa_header);
504
505 /* create LSA */
506 lsa = ospf6_lsa_create(lsa_header);
507
508 SET_FLAG(lsa->flag, OSPF6_LSA_LOCAL_XLT);
509 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
510
511 /* Originate */
512 ospf6_lsa_originate_process(lsa, ospf6);
513
514 if (IS_OSPF6_DEBUG_NSSA)
515 zlog_debug("%s: Originated type5 LSA id %pI4", __func__,
516 &lsa_header->id);
517 return lsa;
518 }
519
520 /* Delete LSA from retransmission list */
521 static void ospf6_ls_retransmit_delete_nbr_as(struct ospf6 *ospf6,
522 struct ospf6_lsa *lsa)
523 {
524 struct listnode *node, *nnode;
525 struct ospf6_area *area;
526
527 if (IS_OSPF6_DEBUG_NSSA)
528 zlog_debug("%s : start lsa %s", __func__, lsa->name);
529
530 /*The function ospf6_flood_clear_area removes LSA from
531 * retransmit list.
532 */
533 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
534 ospf6_flood_clear_area(lsa, area);
535
536 if (IS_OSPF6_DEBUG_NSSA)
537 zlog_debug("%s : finish lsa %s", __func__, lsa->name);
538 }
539
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)
544 {
545 struct ospf6_lsa *new = NULL;
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 struct ospf6_as_external_lsa *ext_lsa;
558 struct ospf6_route *match;
559
560 /* Find the AS external LSA from Type-7 LSA */
561 if (IS_OSPF6_DEBUG_NSSA)
562 zlog_debug(
563 "%s: try to find translated Type-5 LSA for %s",
564 __func__, type7->name);
565
566 ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
567 type7->header);
568 prefix.family = AF_INET6;
569 prefix.prefixlen = ext_lsa->prefix.prefix_length;
570 ospf6_prefix_in6_addr(&prefix.u.prefix6, ext_lsa,
571 &ext_lsa->prefix);
572
573 match = ospf6_route_lookup(&prefix, ospf6->external_table);
574 if (match)
575 type5 = ospf6_lsdb_lookup(
576 htons(OSPF6_LSTYPE_AS_EXTERNAL),
577 match->path.origin.id, ospf6->router_id,
578 ospf6->lsdb);
579 }
580
581 if (type5) {
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);
585
586 /* Flush the LSA */
587 ospf6_lsa_premature_aging(type5);
588 } else {
589 if (IS_OSPF6_DEBUG_NSSA)
590 zlog_debug("%s: Invalid translated LSA %s",
591 __func__, type5->name);
592 return NULL;
593 }
594 }
595
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))
599 == NULL) {
600 if (IS_OSPF6_DEBUG_NSSA)
601 zlog_debug(
602 "%s: Could not translate Type-7 for %pI4",
603 __func__, &type7->header->id);
604 return NULL;
605 }
606 }
607
608 if (IS_OSPF6_DEBUG_NSSA)
609 zlog_debug("%s: finish", __func__);
610
611 return new;
612 }
613
614 static void ospf6_abr_translate_nssa(struct ospf6_area *area,
615 struct ospf6_lsa *lsa)
616 {
617 /* Incoming Type-7 or aggregated Type-7
618 *
619 * LSA is skipped if P-bit is off.
620 *
621 * The Type-7 is translated, Installed/Approved as a Type-5 into
622 * global LSDB, then Flooded through AS
623 *
624 * Later, any Unapproved Translated Type-5's are flushed/discarded
625 */
626
627 struct ospf6_lsa *old = NULL;
628 struct ospf6_as_external_lsa *nssa_lsa;
629 struct prefix prefix;
630 struct ospf6_route *match;
631 struct ospf6 *ospf6;
632
633 ospf6 = area->ospf6;
634 nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
635 lsa->header);
636
637 if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
638 OSPF6_PREFIX_OPTION_P)) {
639 if (IS_OSPF6_DEBUG_NSSA)
640 zlog_debug(
641 "%s : LSA Id %pI4, P-bit off, NO Translation",
642 __func__, &lsa->header->id);
643 return;
644 }
645
646 if (IS_OSPF6_DEBUG_NSSA)
647 zlog_debug(
648 "%s : LSA Id %pI4 external ID %pI4, Translating type 7 to 5",
649 __func__, &lsa->header->id, &lsa->external_lsa_id);
650
651 prefix.family = AF_INET6;
652 prefix.prefixlen = nssa_lsa->prefix.prefix_length;
653 ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa_lsa, &nssa_lsa->prefix);
654
655 if (!CHECK_FLAG(nssa_lsa->bits_metric, OSPF6_ASBR_BIT_F)) {
656 if (IS_OSPF6_DEBUG_NSSA)
657 zlog_debug(
658 "%s : LSA Id %pI4, Forward address is 0, NO Translation",
659 __func__, &lsa->header->id);
660 return;
661 }
662
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,
668 * no need to refresh
669 */
670 if
671 CHECK_FLAG(match->flag, OSPF6_ROUTE_REMOVE)
672 return;
673 } else {
674 if (!CHECK_FLAG(match->flag, OSPF6_ROUTE_REMOVE)) {
675 if (IS_OSPF6_DEBUG_NSSA)
676 zlog_debug(
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,
681 * no need to refresh
682 */
683 return;
684 }
685 }
686 }
687
688 /* Find the existing AS-External LSA for this prefix */
689 match = ospf6_route_lookup(&prefix, ospf6->route_table);
690 if (match) {
691 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
692 lsa->external_lsa_id, ospf6->router_id,
693 ospf6->lsdb);
694 }
695
696 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
697 if (old)
698 ospf6_lsa_premature_aging(old);
699 return;
700 }
701
702 if (old && !OSPF6_LSA_IS_MAXAGE(old)) {
703 if (IS_OSPF6_DEBUG_NSSA)
704 zlog_debug(
705 "%s : found old translated LSA Id %pI4, skip",
706 __func__, &old->header->id);
707
708 UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
709 return;
710
711 } else {
712 /* no existing external route for this LSA Id
713 * originate translated LSA
714 */
715
716 if (ospf6_lsa_translated_nssa_new(area, lsa) == NULL) {
717 if (IS_OSPF6_DEBUG_NSSA)
718 zlog_debug(
719 "%s : Could not translate Type-7 for %pI4 to Type-5",
720 __func__, &lsa->header->id);
721 return;
722 }
723 }
724 }
725
726 static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
727 {
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 ) */
733
734 struct listnode *node;
735 struct ospf6_area *oa;
736 struct ospf6_lsa *lsa;
737 int type;
738
739 if (IS_OSPF6_DEBUG_NSSA)
740 zlog_debug("%s : Start", __func__);
741
742 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
743 if (!IS_AREA_NSSA(oa))
744 continue;
745
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);
751 continue;
752 }
753
754 if (IS_OSPF6_DEBUG_NSSA)
755 zlog_debug("%s : looking at area %pI4", __func__,
756 &oa->area_id);
757
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);
764 }
765 }
766
767 if (IS_OSPF6_DEBUG_NSSA)
768 zlog_debug("%s : Stop", __func__);
769 }
770
771 static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
772 {
773 struct listnode *node;
774 struct ospf6_area *area;
775 struct ospf6_route *range;
776
777 if (IS_OSPF6_DEBUG_NSSA)
778 zlog_debug("%s: Start", __func__);
779
780 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
781 if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
782 continue;
783
784 if (IS_OSPF6_DEBUG_NSSA)
785 zlog_debug("%s: looking at area %pI4", __func__,
786 &area->area_id);
787
788 for (range = ospf6_route_head(area->nssa_range_table); range;
789 range = ospf6_route_next(range))
790 ospf6_abr_range_update(range, ospf6);
791 }
792
793 if (IS_OSPF6_DEBUG_NSSA)
794 zlog_debug("%s: Stop", __func__);
795 }
796
797 static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
798 {
799 struct ospf6_lsa *lsa;
800 uint16_t type;
801
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__);
806
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)) {
811 zlog_debug(
812 "%s : removing unapproved translates, lsa : %s",
813 __func__, lsa->name);
814
815 ospf6_lsa_premature_aging(lsa);
816 }
817 }
818
819 if (IS_OSPF6_DEBUG_NSSA)
820 zlog_debug("%s: Stop", __func__);
821 }
822
823 static void ospf6_abr_nssa_type_7_default_create(struct ospf6 *ospf6,
824 struct ospf6_area *oa)
825 {
826 struct ospf6_route *def;
827 int metric;
828 int metric_type;
829
830 if (IS_OSPF6_DEBUG_NSSA)
831 zlog_debug("Announcing Type-7 default route into NSSA area %s",
832 oa->name);
833
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;
843 else
844 def->path.area_id = oa->area_id;
845
846 /* Compute default route type and metric. */
847 if (oa->nssa_default_originate.metric_value != -1)
848 metric = oa->nssa_default_originate.metric_value;
849 else
850 metric = DEFAULT_DEFAULT_ALWAYS_METRIC;
851 if (oa->nssa_default_originate.metric_type != -1)
852 metric_type = oa->nssa_default_originate.metric_type;
853 else
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;
859 else
860 def->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
861
862 ospf6_nssa_lsa_originate(def, oa, false);
863 ospf6_route_delete(def);
864 }
865
866 static void ospf6_abr_nssa_type_7_default_delete(struct ospf6 *ospf6,
867 struct ospf6_area *oa)
868 {
869 struct ospf6_lsa *lsa;
870
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)
875 zlog_debug(
876 "Withdrawing Type-7 default route from area %s",
877 oa->name);
878
879 ospf6_lsa_purge(lsa);
880 }
881 }
882
883 /* NSSA Type-7 default route. */
884 void ospf6_abr_nssa_type_7_defaults(struct ospf6 *ospf6)
885 {
886 struct listnode *node;
887 struct ospf6_area *oa;
888
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);
895 else
896 ospf6_abr_nssa_type_7_default_delete(ospf6, oa);
897 }
898 }
899
900 static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
901 {
902 if (IS_OSPF6_DEBUG_NSSA)
903 zlog_debug("Check for NSSA-ABR Tasks():");
904
905 if (!IS_OSPF6_ABR(ospf6)) {
906 if (IS_OSPF6_DEBUG_NSSA)
907 zlog_debug("%s Not ABR", __func__);
908 return;
909 }
910
911 if (!ospf6->anyNSSA) {
912 if (IS_OSPF6_DEBUG_NSSA)
913 zlog_debug("%s Not NSSA", __func__);
914 return;
915 }
916
917 /* Each area must confirm TranslatorRole */
918 if (IS_OSPF6_DEBUG_NSSA)
919 zlog_debug("%s: Start", __func__);
920
921 /* For all Global Entries flagged "local-translate", unset APPROVED */
922 if (IS_OSPF6_DEBUG_NSSA)
923 zlog_debug("%s: unapprove translates", __func__);
924
925 ospf6_abr_unapprove_translates(ospf6);
926
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);
931
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
935 */
936 if (IS_OSPF6_DEBUG_NSSA)
937 zlog_debug("%s: process translates", __func__);
938 ospf6_abr_process_nssa_translates(ospf6);
939
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);
944
945 if (IS_OSPF6_DEBUG_NSSA)
946 zlog_debug("%s: Stop", __func__);
947 }
948
949 int ospf6_redistribute_check(struct ospf6 *ospf6, struct ospf6_route *route,
950 int type)
951 {
952 route_map_result_t ret;
953 struct prefix *prefix;
954 struct ospf6_redist *red;
955
956 if (!ospf6_zebra_is_redistribute(type, ospf6->vrf_id))
957 return 0;
958
959 prefix = &route->prefix;
960
961 red = ospf6_redist_lookup(ospf6, type, 0);
962 if (!red)
963 return 0;
964
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) {
970 zlog_warn(
971 "route-map \"%s\" not found, suppress redistributing",
972 ROUTEMAP_NAME(red));
973 return 0;
974 }
975 }
976
977 /* Change to new redist structure */
978 if (ROUTEMAP(red)) {
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\"",
983 ROUTEMAP_NAME(red));
984 return 0;
985 }
986 }
987
988 return 1;
989 }
990
991 /* This function performs ABR related processing */
992 static void ospf6_abr_task_timer(struct thread *thread)
993 {
994 struct ospf6 *ospf6 = THREAD_ARG(thread);
995
996 if (IS_OSPF6_DEBUG_ABR)
997 zlog_debug("Running ABR task on timer");
998
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);
1004 }
1005
1006 void ospf6_schedule_abr_task(struct ospf6 *ospf6)
1007 {
1008 if (thread_is_scheduled(ospf6->t_abr_task)) {
1009 if (IS_OSPF6_DEBUG_ABR)
1010 zlog_debug("ABR task already scheduled");
1011 return;
1012 }
1013
1014 if (IS_OSPF6_DEBUG_ABR)
1015 zlog_debug("Scheduling ABR task");
1016
1017 thread_add_timer(master, ospf6_abr_task_timer, ospf6,
1018 OSPF6_ABR_TASK_DELAY, &ospf6->t_abr_task);
1019 }
1020
1021 /* Flush the NSSA LSAs from the area */
1022 static void ospf6_nssa_flush_area(struct ospf6_area *area)
1023 {
1024 uint16_t type;
1025 struct ospf6_lsa *lsa = NULL, *type5 = NULL;
1026 struct ospf6 *ospf6 = area->ospf6;
1027
1028 if (IS_OSPF6_DEBUG_NSSA)
1029 zlog_debug("%s: area %s", __func__, area->name);
1030
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);
1037
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,
1043 ospf6->lsdb);
1044 if (type5
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);
1049 }
1050 }
1051 }
1052 }
1053
1054 static void ospf6_check_and_originate_type7_lsa(struct ospf6_area *area)
1055 {
1056 struct ospf6_route *route;
1057 struct route_node *rn = NULL;
1058 struct ospf6_external_aggr_rt *aggr;
1059
1060 /* Loop through the external_table to find the LSAs originated
1061 * without aggregation and originate type-7 LSAs for them.
1062 */
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;
1067
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);
1071 }
1072
1073 /* Loop through the aggregation table to originate type-7 LSAs
1074 * for the aggregated type-5 LSAs
1075 */
1076 for (rn = route_top(area->ospf6->rt_aggr_tbl); rn;
1077 rn = route_next(rn)) {
1078 if (!rn->info)
1079 continue;
1080
1081 aggr = rn->info;
1082
1083 if (CHECK_FLAG(aggr->aggrflags,
1084 OSPF6_EXTERNAL_AGGRT_ORIGINATED)) {
1085 if (IS_OSPF6_DEBUG_NSSA)
1086 zlog_debug(
1087 "Originating Type-7 LSAs for area %s",
1088 area->name);
1089
1090 ospf6_nssa_lsa_originate(aggr->route, area, true);
1091 }
1092 }
1093
1094 }
1095
1096 void ospf6_area_nssa_update(struct ospf6_area *area)
1097 {
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;
1110 }
1111
1112 /* Refresh router LSA */
1113 if (IS_AREA_NSSA(area)) {
1114 OSPF6_ROUTER_LSA_SCHEDULE(area);
1115
1116 /* Flush external LSAs. */
1117 ospf6_asbr_remove_externals_from_area(area);
1118
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);
1124 } else {
1125 /* Router is not ABR */
1126 if (IS_OSPF6_DEBUG_NSSA)
1127 zlog_debug("NSSA area %s", area->name);
1128
1129 /* Originate NSSA LSA */
1130 ospf6_check_and_originate_type7_lsa(area);
1131 }
1132 } else {
1133 /* Disable NSSA */
1134 if (IS_OSPF6_DEBUG_NSSA)
1135 zlog_debug("Normal area %s", area->name);
1136 ospf6_nssa_flush_area(area);
1137 }
1138 }
1139
1140 int ospf6_area_nssa_set(struct ospf6 *ospf6, struct ospf6_area *area)
1141 {
1142
1143 if (!IS_AREA_NSSA(area)) {
1144 /* Disable stub first. */
1145 ospf6_area_stub_unset(ospf6, area);
1146
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);
1151 }
1152
1153 return 1;
1154 }
1155
1156 int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
1157 {
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);
1162
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;
1168
1169 ospf6_area_nssa_update(area);
1170 }
1171
1172 return 1;
1173 }
1174
1175 /* Find the NSSA forwarding address */
1176 static struct in6_addr *ospf6_get_nssa_fwd_addr(struct ospf6_area *oa)
1177 {
1178 struct listnode *node, *nnode;
1179 struct ospf6_interface *oi;
1180
1181 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
1182 struct in6_addr *addr;
1183
1184 if (!if_is_operative(oi->interface))
1185 continue;
1186
1187 addr = ospf6_interface_get_global_address(oi->interface);
1188 if (addr)
1189 return addr;
1190 }
1191 return NULL;
1192 }
1193
1194 void ospf6_nssa_lsa_originate(struct ospf6_route *route,
1195 struct ospf6_area *area, bool p_bit)
1196 {
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;
1202
1203 struct ospf6_as_external_lsa *as_external_lsa;
1204 caddr_t p;
1205
1206 if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE(AS_EXTERNAL))
1207 zlog_debug("Originate NSSA-LSA for %pFX", &route->prefix);
1208
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));
1217
1218 /* Fill AS-External-LSA */
1219 /* Metric type */
1220 if (route->path.metric_type == 2)
1221 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1222 else
1223 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
1224
1225 /* external route tag */
1226 if (info && info->tag)
1227 SET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1228 else
1229 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
1230
1231 /* Set metric */
1232 OSPF6_ASBR_METRIC_SET(as_external_lsa, route->path.cost);
1233
1234 /* prefixlen */
1235 as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
1236
1237 /* PrefixOptions */
1238 as_external_lsa->prefix.prefix_options = route->prefix_options;
1239
1240 /* Set the P bit */
1241 if (p_bit)
1242 as_external_lsa->prefix.prefix_options |= OSPF6_PREFIX_OPTION_P;
1243
1244 /* don't use refer LS-type */
1245 as_external_lsa->prefix.prefix_refer_lstype = htons(0);
1246
1247 /* set Prefix */
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);
1252
1253 /* Forwarding address */
1254 fwd_addr = ospf6_get_nssa_fwd_addr(area);
1255 if (fwd_addr) {
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);
1259 } else
1260 UNSET_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
1261
1262 /* External Route Tag */
1263 if (info
1264 && CHECK_FLAG(as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T)) {
1265 route_tag_t network_order = htonl(info->tag);
1266
1267 memcpy(p, &network_order, sizeof(network_order));
1268 p += sizeof(network_order);
1269 }
1270
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);
1280
1281 /* LSA checksum */
1282 ospf6_lsa_checksum(lsa_header);
1283 /* create LSA */
1284 lsa = ospf6_lsa_create(lsa_header);
1285
1286 /* Originate */
1287 ospf6_lsa_originate_area(lsa, area);
1288 }
1289
1290 void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
1291 struct ospf6_lsa *lsa)
1292 {
1293 struct ospf6_lsa *type5 = NULL;
1294 struct ospf6 *ospf6 = area->ospf6;
1295
1296 if (IS_OSPF6_DEBUG_NSSA)
1297 zlog_debug("%s : start", __func__);
1298
1299 if (!ospf6_check_and_set_router_abr(ospf6))
1300 return;
1301
1302 type5 = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
1303 lsa->external_lsa_id, ospf6->router_id,
1304 ospf6->lsdb);
1305 if (!type5) {
1306 if (IS_OSPF6_DEBUG_NSSA)
1307 zlog_debug("%s : Originating type5 LSA", __func__);
1308 ospf6_lsa_translated_nssa_new(area, lsa);
1309 }
1310 }
1311
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")
1324 {
1325 struct ospf6_area *oa;
1326 struct ospf6_route *range;
1327
1328 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1329
1330 OSPF6_CMD_AREA_GET(area, oa, ospf6);
1331
1332 if (!IS_AREA_NSSA(oa)) {
1333 vty_out(vty, "%% First configure %s as an NSSA area\n", area);
1334 return CMD_WARNING;
1335 }
1336
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);
1351 }
1352
1353 /* process "not-advertise" */
1354 if (not_adv)
1355 SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
1356 else
1357 UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
1358
1359 /* process "cost" */
1360 if (!cost_str)
1361 cost = OSPF_AREA_RANGE_COST_UNSPEC;
1362 range->path.u.cost_config = cost;
1363
1364 /* Redo summaries if required */
1365 if (ospf6_check_and_set_router_abr(ospf6))
1366 ospf6_schedule_abr_task(ospf6);
1367
1368 return CMD_SUCCESS;
1369 }
1370
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)>]",
1374 NO_STR
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")
1384 {
1385 struct ospf6_area *oa;
1386 struct ospf6_route *range;
1387
1388 VTY_DECLVAR_CONTEXT(ospf6, ospf6);
1389
1390 OSPF6_CMD_AREA_GET(area, oa, ospf6);
1391
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);
1396 return CMD_SUCCESS;
1397 }
1398
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);
1402
1403 /* Redo summaries if required */
1404 thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
1405 }
1406
1407 ospf6_route_remove(range, oa->nssa_range_table);
1408
1409 return CMD_SUCCESS;
1410 }
1411
1412 DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
1413 "debug ospf6 nssa",
1414 DEBUG_STR
1415 OSPF6_STR
1416 "Debug OSPFv3 NSSA function\n")
1417 {
1418 OSPF6_DEBUG_NSSA_ON();
1419 return CMD_SUCCESS;
1420 }
1421
1422 DEFUN(no_debug_ospf6_nssa, no_debug_ospf6_nssa_cmd,
1423 "no debug ospf6 nssa",
1424 NO_STR
1425 DEBUG_STR
1426 OSPF6_STR
1427 "Debug OSPFv3 NSSA function\n")
1428 {
1429 OSPF6_DEBUG_NSSA_OFF();
1430 return CMD_SUCCESS;
1431 }
1432
1433 void config_write_ospf6_debug_nssa(struct vty *vty)
1434 {
1435 if (IS_OSPF6_DEBUG_NSSA)
1436 vty_out(vty, "debug ospf6 nssa\n");
1437 }
1438
1439 void install_element_ospf6_debug_nssa(void)
1440 {
1441 install_element(OSPF6_NODE, &area_nssa_range_cmd);
1442 install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
1443
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);
1448 }