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