]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_abr.c
Merge pull request #13656 from sri-mohan1/srib-ldpd1
[mirror_frr.git] / ospf6d / ospf6_abr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Area Border Router function.
4 * Copyright (C) 2004 Yasuhiro Ohara
5 */
6
7 #include <zebra.h>
8
9 #include "log.h"
10 #include "prefix.h"
11 #include "table.h"
12 #include "vty.h"
13 #include "linklist.h"
14 #include "command.h"
15 #include "frrevent.h"
16 #include "plist.h"
17 #include "filter.h"
18
19 #include "ospf6_proto.h"
20 #include "ospf6_route.h"
21 #include "ospf6_lsa.h"
22 #include "ospf6_route.h"
23 #include "ospf6_lsdb.h"
24 #include "ospf6_message.h"
25 #include "ospf6_zebra.h"
26
27 #include "ospf6_top.h"
28 #include "ospf6_area.h"
29 #include "ospf6_interface.h"
30 #include "ospf6_neighbor.h"
31
32 #include "ospf6_flood.h"
33 #include "ospf6_intra.h"
34 #include "ospf6_asbr.h"
35 #include "ospf6_abr.h"
36 #include "ospf6d.h"
37 #include "ospf6_nssa.h"
38
39 unsigned char conf_debug_ospf6_abr;
40
41 int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path)
42 {
43 if (((o_path->origin.type == r_path->origin.type)
44 && (o_path->origin.id == r_path->origin.id)
45 && (o_path->origin.adv_router == r_path->origin.adv_router)))
46 return 1;
47 else
48 return 0;
49 }
50
51 bool ospf6_check_and_set_router_abr(struct ospf6 *o)
52 {
53 struct listnode *node;
54 struct ospf6_area *oa;
55 int area_count = 0;
56 bool is_backbone = false;
57
58 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
59 if (IS_OSPF6_DEBUG_ABR)
60 zlog_debug("%s, area_id %pI4", __func__, &oa->area_id);
61 if (IS_AREA_ENABLED(oa))
62 area_count++;
63
64 if (o->backbone == oa)
65 is_backbone = true;
66 }
67
68 if ((area_count > 1) && (is_backbone)) {
69 if (IS_OSPF6_DEBUG_ABR)
70 zlog_debug("%s : set flag OSPF6_FLAG_ABR", __func__);
71 SET_FLAG(o->flag, OSPF6_FLAG_ABR);
72 return true;
73 } else {
74 if (IS_OSPF6_DEBUG_ABR)
75 zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__);
76 UNSET_FLAG(o->flag, OSPF6_FLAG_ABR);
77 return false;
78 }
79 }
80
81 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
82 struct ospf6_area *area)
83 {
84 struct ospf6_interface *oi;
85
86 oi = ospf6_interface_lookup_by_ifindex(
87 ospf6_route_get_first_nh_index(route), area->ospf6->vrf_id);
88 if (oi && oi->area && oi->area == area)
89 return 1;
90 else
91 return 0;
92 }
93
94 static void ospf6_abr_delete_route(struct ospf6_route *summary,
95 struct ospf6_route_table *summary_table,
96 struct ospf6_lsa *old)
97 {
98 if (summary) {
99 ospf6_route_remove(summary, summary_table);
100 }
101
102 if (old && !OSPF6_LSA_IS_MAXAGE(old))
103 ospf6_lsa_purge(old);
104 }
105
106 void ospf6_abr_enable_area(struct ospf6_area *area)
107 {
108 struct ospf6_area *oa;
109 struct listnode *node, *nnode;
110
111 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
112 /* update B bit for each area */
113 OSPF6_ROUTER_LSA_SCHEDULE(oa);
114 }
115
116 void ospf6_abr_disable_area(struct ospf6_area *area)
117 {
118 struct ospf6_area *oa;
119 struct ospf6_route *ro, *nro;
120 struct ospf6_lsa *old;
121 struct listnode *node, *nnode;
122
123 /* Withdraw all summary prefixes previously originated */
124 for (ro = ospf6_route_head(area->summary_prefix); ro; ro = nro) {
125 nro = ospf6_route_next(ro);
126 old = ospf6_lsdb_lookup(ro->path.origin.type,
127 ro->path.origin.id,
128 area->ospf6->router_id, area->lsdb);
129 if (old)
130 ospf6_lsa_purge(old);
131 ospf6_route_remove(ro, area->summary_prefix);
132 }
133
134 /* Withdraw all summary router-routes previously originated */
135 for (ro = ospf6_route_head(area->summary_router); ro; ro = nro) {
136 nro = ospf6_route_next(ro);
137 old = ospf6_lsdb_lookup(ro->path.origin.type,
138 ro->path.origin.id,
139 area->ospf6->router_id, area->lsdb);
140 if (old)
141 ospf6_lsa_purge(old);
142 ospf6_route_remove(ro, area->summary_router);
143 }
144
145 /* Schedule Router-LSA for each area (ABR status may change) */
146 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
147 /* update B bit for each area */
148 OSPF6_ROUTER_LSA_SCHEDULE(oa);
149 }
150
151 /* RFC 2328 12.4.3. Summary-LSAs */
152 /* Returns 1 if a summary LSA has been generated for the area */
153 /* This is used by the area/range logic to add/remove blackhole routes */
154 int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
155 struct ospf6_area *area)
156 {
157 struct ospf6_lsa *lsa, *old = NULL;
158 struct ospf6_route *summary, *range = NULL;
159 struct ospf6_area *route_area;
160 char buffer[OSPF6_MAX_LSASIZE];
161 struct ospf6_lsa_header *lsa_header;
162 caddr_t p;
163 struct ospf6_inter_prefix_lsa *prefix_lsa;
164 struct ospf6_inter_router_lsa *router_lsa;
165 struct ospf6_route_table *summary_table = NULL;
166 uint16_t type;
167 int is_debug = 0;
168
169 if (IS_OSPF6_DEBUG_ABR) {
170 char buf[BUFSIZ];
171
172 if (route->type == OSPF6_DEST_TYPE_ROUTER)
173 inet_ntop(AF_INET,
174 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
175 sizeof(buf));
176 else
177 prefix2str(&route->prefix, buf, sizeof(buf));
178
179 zlog_debug("%s : start area %s, route %s", __func__, area->name,
180 buf);
181 }
182
183 if (route->type == OSPF6_DEST_TYPE_ROUTER)
184 summary_table = area->summary_router;
185 else
186 summary_table = area->summary_prefix;
187
188 summary = ospf6_route_lookup(&route->prefix, summary_table);
189 if (summary) {
190 old = ospf6_lsdb_lookup(summary->path.origin.type,
191 summary->path.origin.id,
192 area->ospf6->router_id, area->lsdb);
193 /* Reset the OSPF6_LSA_UNAPPROVED flag */
194 if (old)
195 UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
196 }
197
198 /* Only destination type network, range or ASBR are considered */
199 if (route->type != OSPF6_DEST_TYPE_NETWORK
200 && route->type != OSPF6_DEST_TYPE_RANGE
201 && ((route->type != OSPF6_DEST_TYPE_ROUTER)
202 || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
203 if (IS_OSPF6_DEBUG_ABR)
204 zlog_debug(
205 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
206 __func__, route->type, route->path.router_bits);
207 return 0;
208 }
209
210 /* AS External routes are never considered */
211 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
212 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
213 if (IS_OSPF6_DEBUG_ABR)
214 zlog_debug("%s : Path type is external, skip",
215 __func__);
216 return 0;
217 }
218
219 /* do not generate if the path's area is the same as target area */
220 if (route->path.area_id == area->area_id) {
221 if (IS_OSPF6_DEBUG_ABR)
222 zlog_debug(
223 "%s: The route is in the area itself, ignore",
224 __func__);
225 return 0;
226 }
227
228 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
229 bool filter = false;
230
231 route_area =
232 ospf6_area_lookup(route->path.area_id, area->ospf6);
233 assert(route_area);
234
235 /* Check export-list */
236 if (EXPORT_LIST(route_area)
237 && access_list_apply(EXPORT_LIST(route_area),
238 &route->prefix)
239 == FILTER_DENY) {
240 if (IS_OSPF6_DEBUG_ABR)
241 zlog_debug(
242 "%s: prefix %pFX was denied by export-list",
243 __func__, &route->prefix);
244 filter = true;
245 }
246
247 /* Check output prefix-list */
248 if (PREFIX_LIST_OUT(route_area)
249 && prefix_list_apply(PREFIX_LIST_OUT(route_area),
250 &route->prefix)
251 != PREFIX_PERMIT) {
252 if (IS_OSPF6_DEBUG_ABR)
253 zlog_debug(
254 "%s: prefix %pFX was denied by prefix-list out",
255 __func__, &route->prefix);
256 filter = true;
257 }
258
259 /* Check import-list */
260 if (IMPORT_LIST(area)
261 && access_list_apply(IMPORT_LIST(area), &route->prefix)
262 == FILTER_DENY) {
263 if (IS_OSPF6_DEBUG_ABR)
264 zlog_debug(
265 "%s: prefix %pFX was denied by import-list",
266 __func__, &route->prefix);
267 filter = true;
268 }
269
270 /* Check input prefix-list */
271 if (PREFIX_LIST_IN(area)
272 && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix)
273 != PREFIX_PERMIT) {
274 if (IS_OSPF6_DEBUG_ABR)
275 zlog_debug(
276 "%s: prefix %pFX was denied by prefix-list in",
277 __func__, &route->prefix);
278 filter = true;
279 }
280
281 if (filter) {
282 if (summary) {
283 ospf6_route_remove(summary, summary_table);
284 if (old)
285 ospf6_lsa_purge(old);
286 }
287 return 0;
288 }
289 }
290
291 /* do not generate if the nexthops belongs to the target area */
292 if (ospf6_abr_nexthops_belong_to_area(route, area)) {
293 if (IS_OSPF6_DEBUG_ABR)
294 zlog_debug(
295 "%s: The route's nexthop is in the same area, ignore",
296 __func__);
297 return 0;
298 }
299
300 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
301 if (ADV_ROUTER_IN_PREFIX(&route->prefix)
302 == area->ospf6->router_id) {
303 if (IS_OSPF6_DEBUG_ABR)
304 zlog_debug(
305 "%s: Skipping ASBR announcement for ABR (%pI4)",
306 __func__,
307 &ADV_ROUTER_IN_PREFIX(&route->prefix));
308 return 0;
309 }
310 }
311
312 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
313 if (IS_OSPF6_DEBUG_ABR
314 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) {
315 is_debug++;
316 if (IS_OSPF6_DEBUG_ABR)
317 zlog_debug(
318 "Originating summary in area %s for ASBR %pI4",
319 area->name,
320 &ADV_ROUTER_IN_PREFIX(&route->prefix));
321 }
322 } else {
323 if (IS_OSPF6_DEBUG_ABR
324 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX))
325 is_debug++;
326
327 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
328 route->path.origin.type ==
329 htons(OSPF6_LSTYPE_INTER_PREFIX)) {
330 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
331 if (is_debug)
332 zlog_debug(
333 "%s: route %pFX with cost %u is not best, ignore.",
334 __func__, &route->prefix,
335 route->path.cost);
336 return 0;
337 }
338 }
339
340 if (route->path.origin.type ==
341 htons(OSPF6_LSTYPE_INTRA_PREFIX)) {
342 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
343 if (is_debug)
344 zlog_debug(
345 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
346 __func__, &route->prefix,
347 route->path.cost);
348 return 0;
349 }
350 }
351
352 if (is_debug)
353 zlog_debug(
354 "Originating summary in area %s for %pFX cost %u",
355 area->name, &route->prefix, route->path.cost);
356 }
357
358 /* if this route has just removed, remove corresponding LSA */
359 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) {
360 if (is_debug)
361 zlog_debug(
362 "The route has just removed, purge previous LSA");
363
364 if (route->type == OSPF6_DEST_TYPE_RANGE) {
365 /* Whether the route have active longer prefix */
366 if (!CHECK_FLAG(route->flag,
367 OSPF6_ROUTE_ACTIVE_SUMMARY)) {
368 if (is_debug)
369 zlog_debug(
370 "The range is not active. withdraw");
371
372 ospf6_abr_delete_route(summary, summary_table,
373 old);
374 }
375 } else if (old) {
376 ospf6_route_remove(summary, summary_table);
377 ospf6_lsa_purge(old);
378 }
379 return 0;
380 }
381
382 if ((route->type == OSPF6_DEST_TYPE_ROUTER)
383 && (IS_AREA_STUB(area) || IS_AREA_NSSA(area))) {
384 if (is_debug)
385 zlog_debug(
386 "Area has been stubbed, purge Inter-Router LSA");
387
388 ospf6_abr_delete_route(summary, summary_table, old);
389 return 0;
390 }
391
392 if (area->no_summary
393 && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) {
394 if (is_debug)
395 zlog_debug("Area has been stubbed, purge prefix LSA");
396
397 ospf6_abr_delete_route(summary, summary_table, old);
398 return 0;
399 }
400
401 /* do not generate if the route cost is greater or equal to LSInfinity
402 */
403 if (route->path.cost >= OSPF_LS_INFINITY) {
404 /* When we're clearing the range route because all active
405 * prefixes
406 * under the range are gone, we set the range's cost to
407 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
408 * don't want to trigger the code here for that. This code is
409 * for
410 * handling routes that have gone to infinity. The range removal
411 * happens
412 * elsewhere.
413 */
414 if ((route->type != OSPF6_DEST_TYPE_RANGE)
415 && (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) {
416 if (is_debug)
417 zlog_debug(
418 "The cost exceeds LSInfinity, withdraw");
419 if (old)
420 ospf6_lsa_purge(old);
421 return 0;
422 }
423 }
424
425 /* if this is a route to ASBR */
426 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
427 /* Only the preferred best path is considered */
428 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
429 if (is_debug)
430 zlog_debug(
431 "This is the secondary path to the ASBR, ignore");
432 ospf6_abr_delete_route(summary, summary_table, old);
433 return 0;
434 }
435
436 /* Do not generate if area is NSSA */
437 route_area =
438 ospf6_area_lookup(route->path.area_id, area->ospf6);
439 assert(route_area);
440
441 if (IS_AREA_NSSA(route_area)) {
442 if (is_debug)
443 zlog_debug(
444 "%s: The route comes from NSSA area, skip",
445 __func__);
446 ospf6_abr_delete_route(summary, summary_table, old);
447 return 0;
448 }
449
450 /* Do not generate if the area is stub */
451 /* XXX */
452 }
453
454 /* if this is an intra-area route, this may be suppressed by aggregation
455 */
456 if (route->type == OSPF6_DEST_TYPE_NETWORK
457 && route->path.type == OSPF6_PATH_TYPE_INTRA) {
458 /* search for configured address range for the route's area */
459 route_area =
460 ospf6_area_lookup(route->path.area_id, area->ospf6);
461 assert(route_area);
462 range = ospf6_route_lookup_bestmatch(&route->prefix,
463 route_area->range_table);
464
465 /* ranges are ignored when originate backbone routes to transit
466 area.
467 Otherwise, if ranges are configured, the route is suppressed.
468 */
469 if (range && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)
470 && (route->path.area_id != OSPF_AREA_BACKBONE
471 || !IS_AREA_TRANSIT(area))) {
472 if (is_debug)
473 zlog_debug(
474 "Suppressed by range %pFX of area %s",
475 &range->prefix, route_area->name);
476 /* The existing summary route could be a range, don't
477 * remove it in this case
478 */
479 if (summary && summary->type != OSPF6_DEST_TYPE_RANGE)
480 ospf6_abr_delete_route(summary, summary_table,
481 old);
482 return 0;
483 }
484 }
485
486 /* If this is a configured address range */
487 if (route->type == OSPF6_DEST_TYPE_RANGE) {
488 /* If DoNotAdvertise is set */
489 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
490 if (is_debug)
491 zlog_debug(
492 "This is the range with DoNotAdvertise set. ignore");
493 ospf6_abr_delete_route(summary, summary_table, old);
494 return 0;
495 }
496
497 /* If there are no active prefixes in this range, remove */
498 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
499 if (is_debug)
500 zlog_debug("The range is not active. withdraw");
501 ospf6_abr_delete_route(summary, summary_table, old);
502 return 0;
503 }
504 }
505
506 /* the route is going to be originated. store it in area's summary_table
507 */
508 if (summary == NULL) {
509 summary = ospf6_route_copy(route);
510 summary->path.origin.adv_router = area->ospf6->router_id;
511
512 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
513 summary->path.origin.type =
514 htons(OSPF6_LSTYPE_INTER_ROUTER);
515 summary->path.origin.id =
516 ADV_ROUTER_IN_PREFIX(&route->prefix);
517 } else {
518 struct ospf6_lsa *old;
519
520 summary->path.origin.type =
521 htons(OSPF6_LSTYPE_INTER_PREFIX);
522
523 /* Try to reuse LS-ID from previous running instance. */
524 old = ospf6_find_inter_prefix_lsa(area->ospf6, area,
525 &route->prefix);
526 if (old)
527 summary->path.origin.id = old->header->id;
528 else
529 summary->path.origin.id = ospf6_new_ls_id(
530 summary->path.origin.type,
531 summary->path.origin.adv_router,
532 area->lsdb);
533 }
534 summary = ospf6_route_add(summary, summary_table);
535 } else {
536 summary->type = route->type;
537 monotime(&summary->changed);
538 }
539
540 summary->prefix_options = route->prefix_options;
541 summary->path.router_bits = route->path.router_bits;
542 summary->path.options[0] = route->path.options[0];
543 summary->path.options[1] = route->path.options[1];
544 summary->path.options[2] = route->path.options[2];
545 summary->path.area_id = area->area_id;
546 summary->path.type = OSPF6_PATH_TYPE_INTER;
547 summary->path.subtype = route->path.subtype;
548 summary->path.cost = route->path.cost;
549 /* summary->nexthop[0] = route->nexthop[0]; */
550
551 /* prepare buffer */
552 memset(buffer, 0, sizeof(buffer));
553 lsa_header = (struct ospf6_lsa_header *)buffer;
554
555 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
556 router_lsa = (struct ospf6_inter_router_lsa
557 *)((caddr_t)lsa_header
558 + sizeof(struct ospf6_lsa_header));
559 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
560
561 /* Fill Inter-Area-Router-LSA */
562 router_lsa->options[0] = route->path.options[0];
563 router_lsa->options[1] = route->path.options[1];
564 router_lsa->options[2] = route->path.options[2];
565 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
566 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
567 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
568 } else {
569 prefix_lsa = (struct ospf6_inter_prefix_lsa
570 *)((caddr_t)lsa_header
571 + sizeof(struct ospf6_lsa_header));
572 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
573
574 /* Fill Inter-Area-Prefix-LSA */
575 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
576 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
577 prefix_lsa->prefix.prefix_options = route->prefix_options;
578
579 /* set Prefix */
580 memcpy(p, &route->prefix.u.prefix6,
581 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
582 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
583 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
584 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
585 }
586
587 /* Fill LSA Header */
588 lsa_header->age = 0;
589 lsa_header->type = type;
590 lsa_header->id = summary->path.origin.id;
591 lsa_header->adv_router = area->ospf6->router_id;
592 lsa_header->seqnum =
593 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
594 lsa_header->adv_router, area->lsdb);
595 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
596
597 /* LSA checksum */
598 ospf6_lsa_checksum(lsa_header);
599
600 /* create LSA */
601 lsa = ospf6_lsa_create(lsa_header);
602
603 /* Reset the unapproved flag */
604 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
605
606 /* Originate */
607 ospf6_lsa_originate_area(lsa, area);
608
609 if (IS_OSPF6_DEBUG_ABR)
610 zlog_debug("%s : finish area %s", __func__, area->name);
611
612 return 1;
613 }
614
615 void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
616 {
617 struct listnode *node, *nnode;
618 struct ospf6_area *oa;
619 struct ospf6_route *range;
620
621 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
622 for (range = ospf6_route_head(oa->range_table); range;
623 range = ospf6_route_next(range))
624 OSPF6_ABR_RANGE_CLEAR_COST(range);
625 for (range = ospf6_route_head(oa->nssa_range_table); range;
626 range = ospf6_route_next(range))
627 OSPF6_ABR_RANGE_CLEAR_COST(range);
628 }
629 }
630
631 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
632 struct ospf6 *o)
633 {
634 struct ospf6_route *ro;
635 uint32_t cost = 0;
636
637 for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
638 ro = ospf6_route_match_next(&range->prefix, ro)) {
639 if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
640 continue;
641 if (ro->path.area_id != range->path.area_id)
642 continue;
643 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
644 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
645 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
646 continue;
647 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
648 && ro->path.type != OSPF6_PATH_TYPE_INTRA)
649 continue;
650
651 cost = MAX(cost, ro->path.cost);
652 }
653
654 return cost;
655 }
656
657 static inline int
658 ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
659 {
660 int redo_summary = 0;
661
662 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
663 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
664 redo_summary = 1;
665 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
666 if (range->path.cost != 0) {
667 range->path.cost = 0;
668 redo_summary = 1;
669 }
670 } else if (cost) {
671 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
672 && range->path.cost != range->path.u.cost_config)) {
673 range->path.cost = range->path.u.cost_config;
674 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
675 redo_summary = 1;
676 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
677 && range->path.cost != cost) {
678 range->path.cost = cost;
679 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
680 redo_summary = 1;
681 }
682 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
683 /* Cost is zero, meaning no active range */
684 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
685 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
686 redo_summary = 1;
687 }
688
689 return (redo_summary);
690 }
691
692 void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
693 {
694 uint32_t cost = 0;
695 struct listnode *node, *nnode;
696 struct ospf6_area *oa;
697 int summary_orig = 0;
698
699 assert(range->type == OSPF6_DEST_TYPE_RANGE);
700 oa = ospf6_area_lookup(range->path.area_id, ospf6);
701 assert(oa);
702
703 /* update range's cost and active flag */
704 cost = ospf6_abr_range_compute_cost(range, ospf6);
705
706 if (IS_OSPF6_DEBUG_ABR)
707 zlog_debug("%s: range %pFX, cost %d", __func__, &range->prefix,
708 cost);
709
710 /* Non-zero cost is a proxy for active longer prefixes in this range.
711 * If there are active routes covered by this range AND either the
712 * configured
713 * cost has changed or the summarized cost has changed then redo
714 * summaries.
715 * Alternately, if there are no longer active prefixes and there are
716 * summary announcements, withdraw those announcements.
717 *
718 * The don't advertise code relies on the path.cost being set to UNSPEC
719 * to
720 * work the first time. Subsequent times the path.cost is not 0 anyway
721 * if there
722 * were active ranges.
723 */
724 if (!ospf6_abr_range_summary_needs_update(range, cost))
725 return;
726
727 if (IS_OSPF6_DEBUG_ABR)
728 zlog_debug("%s: range %pFX update", __func__, &range->prefix);
729
730 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
731 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
732 && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
733 ospf6_nssa_lsa_originate(range, oa, true);
734 summary_orig = 1;
735 } else {
736 struct ospf6_lsa *lsa;
737
738 lsa = ospf6_lsdb_lookup(range->path.origin.type,
739 range->path.origin.id,
740 ospf6->router_id, oa->lsdb);
741 if (lsa)
742 ospf6_lsa_premature_aging(lsa);
743 }
744 } else {
745 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
746 summary_orig +=
747 ospf6_abr_originate_summary_to_area(range, oa);
748 }
749 }
750
751 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
752 && summary_orig) {
753 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
754 if (IS_OSPF6_DEBUG_ABR)
755 zlog_debug("Add discard route");
756
757 ospf6_zebra_add_discard(range, ospf6);
758 }
759 } else {
760 /* Summary removed or no summary generated as no
761 * specifics exist */
762 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
763 if (IS_OSPF6_DEBUG_ABR)
764 zlog_debug("Delete discard route");
765
766 ospf6_zebra_delete_discard(range, ospf6);
767 }
768 }
769 }
770
771 void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
772 {
773 struct listnode *node, *nnode;
774 struct ospf6_area *oa;
775 struct ospf6_route *range = NULL;
776
777 if (IS_OSPF6_DEBUG_ABR) {
778 char buf[BUFSIZ];
779
780 if (route->type == OSPF6_DEST_TYPE_ROUTER)
781 inet_ntop(AF_INET,
782 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
783 sizeof(buf));
784 else
785 prefix2str(&route->prefix, buf, sizeof(buf));
786
787 zlog_debug("%s: route %s", __func__, buf);
788 }
789
790 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
791 oa = ospf6_area_lookup(route->path.area_id, ospf6);
792 if (!oa) {
793 zlog_err("OSPFv6 area lookup failed");
794 return;
795 }
796
797 range = ospf6_route_lookup_bestmatch(&route->prefix,
798 oa->range_table);
799 if (range) {
800 ospf6_abr_range_update(range, ospf6);
801 }
802 }
803
804 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
805 ospf6_abr_originate_summary_to_area(route, oa);
806 }
807
808 void ospf6_abr_defaults_to_stub(struct ospf6 *o)
809 {
810 struct listnode *node, *nnode;
811 struct ospf6_area *oa;
812 struct ospf6_route *def, *route;
813 int type = DEFAULT_ROUTE;
814
815 if (!o->backbone)
816 return;
817
818 def = ospf6_route_create(o);
819 def->type = OSPF6_DEST_TYPE_NETWORK;
820 def->prefix.family = AF_INET6;
821 def->prefix.prefixlen = 0;
822 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
823 def->type = OSPF6_DEST_TYPE_NETWORK;
824 def->path.type = OSPF6_PATH_TYPE_INTER;
825 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
826 def->path.area_id = o->backbone->area_id;
827 def->path.metric_type = metric_type(o, type, 0);
828 def->path.cost = metric_value(o, type, 0);
829
830 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
831 if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
832 /* announce defaults to stubby areas */
833 if (IS_OSPF6_DEBUG_ABR)
834 zlog_debug(
835 "Announcing default route into stubby area %s",
836 oa->name);
837 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
838 ospf6_abr_originate_summary_to_area(def, oa);
839 } else {
840 /* withdraw defaults when an area switches from stub to
841 * non-stub */
842 route = ospf6_route_lookup(&def->prefix,
843 oa->summary_prefix);
844 if (route
845 && (route->path.subtype == def->path.subtype)) {
846 if (IS_OSPF6_DEBUG_ABR)
847 zlog_debug(
848 "Withdrawing default route from non-stubby area %s",
849 oa->name);
850 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
851 ospf6_abr_originate_summary_to_area(def, oa);
852 }
853 }
854 }
855 ospf6_route_delete(def);
856 }
857
858 void ospf6_abr_old_path_update(struct ospf6_route *old_route,
859 struct ospf6_route *route,
860 struct ospf6_route_table *table)
861 {
862 struct ospf6_path *o_path = NULL;
863 struct listnode *anode, *anext;
864 struct listnode *nnode, *rnode, *rnext;
865 struct ospf6_nexthop *nh, *rnh;
866
867 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
868 if (o_path->area_id != route->path.area_id
869 || !ospf6_ls_origin_same(o_path, &route->path))
870 continue;
871
872 if ((o_path->cost == route->path.cost) &&
873 (o_path->u.cost_e2 == route->path.u.cost_e2))
874 continue;
875
876 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
877 for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
878 rnext, rnh)) {
879 if (!ospf6_nexthop_is_same(rnh, nh))
880 continue;
881 listnode_delete(old_route->nh_list, rnh);
882 ospf6_nexthop_delete(rnh);
883 }
884
885 }
886
887 listnode_delete(old_route->paths, o_path);
888 ospf6_path_free(o_path);
889
890 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
891 anext, o_path)) {
892 ospf6_merge_nexthops(old_route->nh_list,
893 o_path->nh_list);
894 }
895
896 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
897 zlog_debug("%s: paths %u nh %u", __func__,
898 old_route->paths
899 ? listcount(old_route->paths)
900 : 0,
901 old_route->nh_list
902 ? listcount(old_route->nh_list)
903 : 0);
904
905 if (table->hook_add)
906 (*table->hook_add)(old_route);
907
908 if (old_route->path.origin.id == route->path.origin.id &&
909 old_route->path.origin.adv_router ==
910 route->path.origin.adv_router) {
911 struct ospf6_path *h_path;
912
913 h_path = (struct ospf6_path *)
914 listgetdata(listhead(old_route->paths));
915 old_route->path.origin.type = h_path->origin.type;
916 old_route->path.origin.id = h_path->origin.id;
917 old_route->path.origin.adv_router =
918 h_path->origin.adv_router;
919 }
920 }
921 }
922
923 void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
924 struct ospf6_route_table *table)
925 {
926 if (IS_OSPF6_DEBUG_ABR)
927 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
928 listcount(old->paths));
929
930 if (listcount(old->paths) > 1) {
931 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
932 struct ospf6_path *o_path;
933 struct ospf6_nexthop *nh, *rnh;
934 bool nh_updated = false;
935
936 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
937 if (o_path->origin.adv_router != lsa->header->adv_router
938 || o_path->origin.id != lsa->header->id)
939 continue;
940 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
941 for (ALL_LIST_ELEMENTS(old->nh_list,
942 rnode, rnext, rnh)) {
943 if (!ospf6_nexthop_is_same(rnh, nh))
944 continue;
945 if (IS_OSPF6_DEBUG_ABR)
946 zlog_debug("deleted nexthop");
947 listnode_delete(old->nh_list, rnh);
948 ospf6_nexthop_delete(rnh);
949 }
950 }
951 listnode_delete(old->paths, o_path);
952 ospf6_path_free(o_path);
953 nh_updated = true;
954 }
955
956 if (nh_updated) {
957 if (listcount(old->paths)) {
958 if (IS_OSPF6_DEBUG_ABR
959 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
960 zlog_debug("%s: old %pFX updated nh %u",
961 __func__, &old->prefix,
962 old->nh_list ? listcount(
963 old->nh_list)
964 : 0);
965
966 if (table->hook_add)
967 (*table->hook_add)(old);
968
969 if ((old->path.origin.id == lsa->header->id) &&
970 (old->path.origin.adv_router
971 == lsa->header->adv_router)) {
972 struct ospf6_path *h_path;
973
974 h_path = (struct ospf6_path *)
975 listgetdata(
976 listhead(old->paths));
977 old->path.origin.type =
978 h_path->origin.type;
979 old->path.origin.id = h_path->origin.id;
980 old->path.origin.adv_router =
981 h_path->origin.adv_router;
982 }
983 } else
984 ospf6_route_remove(old, table);
985 }
986 } else
987 ospf6_route_remove(old, table);
988 }
989
990 /* RFC 2328 16.2. Calculating the inter-area routes */
991 void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
992 {
993 struct prefix prefix, abr_prefix;
994 struct ospf6_route_table *table = NULL;
995 struct ospf6_route *range, *route, *old = NULL, *old_route;
996 struct ospf6_route *abr_entry;
997 uint8_t type = 0;
998 char options[3] = {0, 0, 0};
999 uint8_t prefix_options = 0;
1000 uint32_t cost = 0;
1001 uint8_t router_bits = 0;
1002 char buf[PREFIX2STR_BUFFER];
1003 int is_debug = 0;
1004 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
1005 struct ospf6_inter_router_lsa *router_lsa = NULL;
1006 bool old_entry_updated = false;
1007 struct ospf6_path *path, *o_path, *ecmp_path;
1008 struct listnode *anode;
1009 bool add_route = false;
1010
1011 memset(&prefix, 0, sizeof(prefix));
1012
1013 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1014 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
1015 is_debug++;
1016 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1017 lsa->name, ospf6_lsa_age_current(lsa),
1018 oa->name);
1019 }
1020
1021 prefix_lsa =
1022 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1023 lsa->header);
1024 prefix.family = AF_INET6;
1025 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
1026 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
1027 &prefix_lsa->prefix);
1028 if (is_debug)
1029 prefix2str(&prefix, buf, sizeof(buf));
1030 table = oa->ospf6->route_table;
1031 type = OSPF6_DEST_TYPE_NETWORK;
1032 prefix_options = prefix_lsa->prefix.prefix_options;
1033 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
1034 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1035 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
1036 is_debug++;
1037 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1038 lsa->name, ospf6_lsa_age_current(lsa),
1039 oa->name);
1040 }
1041
1042 router_lsa =
1043 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1044 lsa->header);
1045 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
1046 &prefix);
1047 if (is_debug)
1048 inet_ntop(AF_INET, &router_lsa->router_id, buf,
1049 sizeof(buf));
1050
1051 table = oa->ospf6->brouter_table;
1052 type = OSPF6_DEST_TYPE_ROUTER;
1053 options[0] = router_lsa->options[0];
1054 options[1] = router_lsa->options[1];
1055 options[2] = router_lsa->options[2];
1056 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
1057 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
1058 } else
1059 assert(0);
1060
1061 /* Find existing route */
1062 route = ospf6_route_lookup(&prefix, table);
1063 if (route) {
1064 ospf6_route_lock(route);
1065 if (is_debug)
1066 zlog_debug("%s: route %pFX, paths %d", __func__,
1067 &prefix, listcount(route->paths));
1068 }
1069 while (route && ospf6_route_is_prefix(&prefix, route)) {
1070 if (route->path.area_id == oa->area_id
1071 && route->path.origin.type == lsa->header->type
1072 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
1073 /* LSA adv. router could be part of route's
1074 * paths list. Find the existing path and set
1075 * old as the route.
1076 */
1077 if (listcount(route->paths) > 1) {
1078 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
1079 o_path)) {
1080 if (o_path->origin.id == lsa->header->id
1081 && o_path->origin.adv_router ==
1082 lsa->header->adv_router) {
1083 old = route;
1084
1085 if (is_debug)
1086 zlog_debug(
1087 "%s: old entry found in paths, adv_router %pI4",
1088 __func__,
1089 &o_path->origin.adv_router);
1090
1091 break;
1092 }
1093 }
1094 } else if (route->path.origin.id == lsa->header->id &&
1095 route->path.origin.adv_router ==
1096 lsa->header->adv_router)
1097 old = route;
1098 }
1099 route = ospf6_route_next(route);
1100 }
1101 if (route)
1102 ospf6_route_unlock(route);
1103
1104 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1105 if (cost == OSPF_LS_INFINITY) {
1106 if (is_debug)
1107 zlog_debug("cost is LS_INFINITY, ignore");
1108 if (old)
1109 ospf6_abr_old_route_remove(lsa, old, table);
1110 return;
1111 }
1112 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
1113 if (is_debug)
1114 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
1115 lsa->name);
1116 if (old)
1117 ospf6_abr_old_route_remove(lsa, old, table);
1118 return;
1119 }
1120
1121
1122 /* (2) if the LSA is self-originated, ignore */
1123 if (lsa->header->adv_router == oa->ospf6->router_id) {
1124 if (is_debug)
1125 zlog_debug("LSA %s is self-originated, ignore",
1126 lsa->name);
1127 if (old)
1128 ospf6_route_remove(old, table);
1129 return;
1130 }
1131
1132 /* (3) if the prefix is equal to an active configured address range */
1133 /* or if the NU bit is set in the prefix */
1134 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1135 /* must have been set in previous block */
1136 assert(prefix_lsa);
1137
1138 range = ospf6_route_lookup(&prefix, oa->range_table);
1139 if (range) {
1140 if (is_debug)
1141 zlog_debug(
1142 "Prefix is equal to address range, ignore");
1143 if (old)
1144 ospf6_route_remove(old, table);
1145 return;
1146 }
1147
1148 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1149 OSPF6_PREFIX_OPTION_NU)) {
1150 if (is_debug)
1151 zlog_debug("Prefix has the NU bit set, ignore");
1152 if (old)
1153 ospf6_route_remove(old, table);
1154 return;
1155 }
1156 }
1157
1158 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1159 /* To pass test suites */
1160 assert(router_lsa);
1161 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
1162 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
1163 if (is_debug)
1164 zlog_debug(
1165 "Router-LSA has the V6-bit or R-bit unset, ignore");
1166 if (old)
1167 ospf6_route_remove(old, table);
1168
1169 return;
1170 }
1171 /* Avoid infinite recursion if someone has maliciously announced
1172 an
1173 Inter-Router LSA for an ABR
1174 */
1175 if (lsa->header->adv_router == router_lsa->router_id) {
1176 if (is_debug)
1177 zlog_debug(
1178 "Ignoring Inter-Router LSA for an ABR (%s)",
1179 buf);
1180 if (old)
1181 ospf6_route_remove(old, table);
1182
1183 return;
1184 }
1185 }
1186
1187 /* (4) if the routing table entry for the ABR does not exist */
1188 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
1189 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
1190 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
1191 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
1192 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
1193 if (is_debug)
1194 zlog_debug(
1195 "%s: ABR router entry %pFX does not exist, ignore",
1196 __func__, &abr_prefix);
1197 if (old) {
1198 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
1199 oa->intra_brouter_calc) {
1200 if (is_debug)
1201 zlog_debug(
1202 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1203 __func__, buf, (void *)old);
1204 } else {
1205 if (is_debug)
1206 zlog_debug(
1207 "%s: remove old entry: %s %p ",
1208 __func__, buf, (void *)old);
1209 ospf6_abr_old_route_remove(lsa, old, table);
1210 }
1211 }
1212 return;
1213 }
1214
1215 /* (5),(6): the path preference is handled by the sorting
1216 in the routing table. Always install the path by substituting
1217 old route (if any). */
1218 route = ospf6_route_create(oa->ospf6);
1219
1220 route->type = type;
1221 route->prefix = prefix;
1222 route->prefix_options = prefix_options;
1223 route->path.origin.type = lsa->header->type;
1224 route->path.origin.id = lsa->header->id;
1225 route->path.origin.adv_router = lsa->header->adv_router;
1226 route->path.router_bits = router_bits;
1227 route->path.options[0] = options[0];
1228 route->path.options[1] = options[1];
1229 route->path.options[2] = options[2];
1230 route->path.area_id = oa->area_id;
1231 route->path.type = OSPF6_PATH_TYPE_INTER;
1232 route->path.cost = abr_entry->path.cost + cost;
1233
1234 /* copy brouter rechable nexthops into the route. */
1235 ospf6_route_copy_nexthops(route, abr_entry);
1236
1237 /* (7) If the routes are identical, copy the next hops over to existing
1238 route. ospf6's route table implementation will otherwise string both
1239 routes, but keep the older one as the best route since the routes
1240 are identical.
1241 */
1242 old = ospf6_route_lookup(&prefix, table);
1243 if (old) {
1244 if (is_debug)
1245 zlog_debug("%s: found old route %pFX, paths %d",
1246 __func__, &prefix, listcount(old->paths));
1247 }
1248 for (old_route = old; old_route; old_route = old_route->next) {
1249
1250 /* The route linked-list is grouped in batches of prefix.
1251 * If the new prefix is not the same as the one of interest
1252 * then we have walked over the end of the batch and so we
1253 * should break rather than continuing unnecessarily.
1254 */
1255 if (!ospf6_route_is_same(old_route, route))
1256 break;
1257 if ((old_route->type != route->type)
1258 || (old_route->path.type != route->path.type))
1259 continue;
1260
1261 if ((ospf6_route_cmp(route, old_route) != 0)) {
1262 if (is_debug)
1263 zlog_debug(
1264 "%s: old %p %pFX cost %u new route cost %u are not same",
1265 __func__, (void *)old_route, &prefix,
1266 old_route->path.cost, route->path.cost);
1267
1268 /* Check new route's adv. router is same in one of
1269 * the paths with differed cost, if so remove the
1270 * old path as later new route will be added.
1271 */
1272 if (listcount(old_route->paths) > 1)
1273 ospf6_abr_old_path_update(old_route, route,
1274 table);
1275 continue;
1276 }
1277
1278 list_delete_all_node(old_route->nh_list);
1279 ospf6_route_copy_nexthops(old_route, route);
1280 old_entry_updated = true;
1281
1282 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1283 o_path)) {
1284 if (o_path->area_id == route->path.area_id
1285 && ospf6_ls_origin_same(o_path, &route->path))
1286 break;
1287 }
1288
1289 /* New adv. router for a existing path add to paths list */
1290 if (o_path == NULL) {
1291 ecmp_path = ospf6_path_dup(&route->path);
1292
1293 /* Add a nh_list to new ecmp path */
1294 ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
1295
1296 /* Add the new path to route's path list */
1297 listnode_add_sort(old_route->paths, ecmp_path);
1298
1299 if (is_debug) {
1300 zlog_debug(
1301 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1302 __func__, &route->prefix,
1303 old_route->path.cost,
1304 &ecmp_path->origin.adv_router,
1305 listcount(ecmp_path->nh_list),
1306 old_route->paths
1307 ? listcount(old_route->paths)
1308 : 0,
1309 listcount(old_route->nh_list));
1310 }
1311 } else {
1312 struct ospf6_route *tmp_route;
1313
1314 tmp_route = ospf6_route_create(oa->ospf6);
1315
1316 ospf6_copy_nexthops(tmp_route->nh_list,
1317 o_path->nh_list);
1318
1319 if (!ospf6_route_cmp_nexthops(tmp_route, route)) {
1320 /* adv. router exists in the list, update nhs */
1321 list_delete_all_node(o_path->nh_list);
1322 ospf6_copy_nexthops(o_path->nh_list,
1323 route->nh_list);
1324 ospf6_route_delete(tmp_route);
1325 } else {
1326 /* adv. router has no change in nhs */
1327 old_entry_updated = false;
1328 ospf6_route_delete(tmp_route);
1329 continue;
1330 }
1331 }
1332
1333 if (is_debug)
1334 zlog_debug(
1335 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1336 __func__, buf, (void *)old_route,
1337 old_route->path.cost, route->path.cost,
1338 listcount(old_route->nh_list));
1339
1340 /* For Inter-Prefix route: Update RIB/FIB,
1341 * For Inter-Router trigger summary update
1342 */
1343 if (table->hook_add)
1344 (*table->hook_add)(old_route);
1345
1346 break;
1347 }
1348
1349 /* If the old entry is not updated and old entry not found or old entry
1350 * does not match with the new entry then add the new route
1351 */
1352 if (old_entry_updated == false) {
1353 if ((old == NULL) || (old->type != route->type)
1354 || (old->path.type != route->path.type)
1355 || (old->path.cost != route->path.cost))
1356 add_route = true;
1357 }
1358
1359 if (add_route) {
1360 if (is_debug) {
1361 zlog_debug(
1362 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1363 __func__, buf, route->path.cost,
1364 listcount(route->nh_list),
1365 &route->path.origin.adv_router);
1366 }
1367
1368 path = ospf6_path_dup(&route->path);
1369 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
1370 listnode_add_sort(route->paths, path);
1371 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1372 ospf6_route_add(route, table);
1373 } else
1374 /* if we did not add the route remove it */
1375 ospf6_route_delete(route);
1376 }
1377
1378 void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
1379 struct ospf6 *ospf6)
1380 {
1381 struct ospf6_lsa *lsa;
1382 struct ospf6_area *oa;
1383 uint16_t type;
1384
1385 oa = ospf6_area_lookup(route->path.area_id, ospf6);
1386 /*
1387 * It is possible to designate a non backbone
1388 * area first. If that is the case safely
1389 * fall out of this function.
1390 */
1391 if (oa == NULL)
1392 return;
1393
1394 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1395 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1396 ospf6_abr_examin_summary(lsa, oa);
1397
1398 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1399 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1400 ospf6_abr_examin_summary(lsa, oa);
1401 }
1402
1403 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
1404 {
1405 struct ospf6_route *route;
1406
1407 if (IS_OSPF6_DEBUG_ABR)
1408 zlog_debug("Re-examining Inter-Prefix Summaries");
1409
1410 for (route = ospf6_route_head(o->route_table); route;
1411 route = ospf6_route_next(route))
1412 ospf6_abr_originate_summary(route, o);
1413
1414 if (IS_OSPF6_DEBUG_ABR)
1415 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1416 }
1417
1418
1419 /* Display functions */
1420 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1421 char *buf, int buflen,
1422 int pos)
1423 {
1424 struct ospf6_inter_prefix_lsa *prefix_lsa;
1425 struct in6_addr in6;
1426 char tbuf[16];
1427
1428 if (lsa != NULL) {
1429 prefix_lsa =
1430 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1431 lsa->header);
1432
1433 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
1434 if (buf) {
1435 inet_ntop(AF_INET6, &in6, buf, buflen);
1436 snprintf(tbuf, sizeof(tbuf), "/%d",
1437 prefix_lsa->prefix.prefix_length);
1438 strlcat(buf, tbuf, buflen);
1439 }
1440 }
1441
1442 return (buf);
1443 }
1444
1445 static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1446 struct ospf6_lsa *lsa,
1447 json_object *json_obj,
1448 bool use_json)
1449 {
1450 struct ospf6_inter_prefix_lsa *prefix_lsa;
1451 char buf[INET6_ADDRSTRLEN];
1452
1453 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1454 lsa->header);
1455
1456 if (use_json) {
1457 json_object_int_add(
1458 json_obj, "metric",
1459 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1460 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1461 buf, sizeof(buf));
1462 json_object_string_add(json_obj, "prefixOptions", buf);
1463 json_object_string_add(
1464 json_obj, "prefix",
1465 ospf6_inter_area_prefix_lsa_get_prefix_str(
1466 lsa, buf, sizeof(buf), 0));
1467 } else {
1468 vty_out(vty, " Metric: %lu\n",
1469 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1470
1471 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1472 buf, sizeof(buf));
1473 vty_out(vty, " Prefix Options: %s\n", buf);
1474
1475 vty_out(vty, " Prefix: %s\n",
1476 ospf6_inter_area_prefix_lsa_get_prefix_str(
1477 lsa, buf, sizeof(buf), 0));
1478 }
1479
1480 return 0;
1481 }
1482
1483 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1484 char *buf, int buflen,
1485 int pos)
1486 {
1487 struct ospf6_inter_router_lsa *router_lsa;
1488
1489 if (lsa != NULL) {
1490 router_lsa =
1491 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1492 lsa->header);
1493
1494
1495 if (buf)
1496 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1497 }
1498
1499 return (buf);
1500 }
1501
1502 static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1503 struct ospf6_lsa *lsa,
1504 json_object *json_obj,
1505 bool use_json)
1506 {
1507 struct ospf6_inter_router_lsa *router_lsa;
1508 char buf[64];
1509
1510 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1511 lsa->header);
1512
1513 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1514 if (use_json) {
1515 json_object_string_add(json_obj, "options", buf);
1516 json_object_int_add(
1517 json_obj, "metric",
1518 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1519 } else {
1520 vty_out(vty, " Options: %s\n", buf);
1521 vty_out(vty, " Metric: %lu\n",
1522 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1523 }
1524
1525 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1526 if (use_json)
1527 json_object_string_add(json_obj, "destinationRouterId", buf);
1528 else
1529 vty_out(vty, " Destination Router ID: %s\n", buf);
1530
1531 return 0;
1532 }
1533
1534 /* Debug commands */
1535 DEFUN (debug_ospf6_abr,
1536 debug_ospf6_abr_cmd,
1537 "debug ospf6 abr",
1538 DEBUG_STR
1539 OSPF6_STR
1540 "Debug OSPFv3 ABR function\n"
1541 )
1542 {
1543 OSPF6_DEBUG_ABR_ON();
1544 return CMD_SUCCESS;
1545 }
1546
1547 DEFUN (no_debug_ospf6_abr,
1548 no_debug_ospf6_abr_cmd,
1549 "no debug ospf6 abr",
1550 NO_STR
1551 DEBUG_STR
1552 OSPF6_STR
1553 "Debug OSPFv3 ABR function\n"
1554 )
1555 {
1556 OSPF6_DEBUG_ABR_OFF();
1557 return CMD_SUCCESS;
1558 }
1559
1560 int config_write_ospf6_debug_abr(struct vty *vty)
1561 {
1562 if (IS_OSPF6_DEBUG_ABR)
1563 vty_out(vty, "debug ospf6 abr\n");
1564 return 0;
1565 }
1566
1567 void install_element_ospf6_debug_abr(void)
1568 {
1569 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1570 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1571 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1572 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1573 }
1574
1575 static struct ospf6_lsa_handler inter_prefix_handler = {
1576 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1577 .lh_name = "Inter-Prefix",
1578 .lh_short_name = "IAP",
1579 .lh_show = ospf6_inter_area_prefix_lsa_show,
1580 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
1581 .lh_debug = 0};
1582
1583 static struct ospf6_lsa_handler inter_router_handler = {
1584 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1585 .lh_name = "Inter-Router",
1586 .lh_short_name = "IAR",
1587 .lh_show = ospf6_inter_area_router_lsa_show,
1588 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
1589 .lh_debug = 0};
1590
1591 void ospf6_abr_init(void)
1592 {
1593 ospf6_install_lsa_handler(&inter_prefix_handler);
1594 ospf6_install_lsa_handler(&inter_router_handler);
1595 }