]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_abr.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[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 "thread.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 summary->path.origin.type =
519 htons(OSPF6_LSTYPE_INTER_PREFIX);
520 summary->path.origin.id = ospf6_new_ls_id(
521 summary->path.origin.type,
522 summary->path.origin.adv_router, area->lsdb);
523 }
524 summary = ospf6_route_add(summary, summary_table);
525 } else {
526 summary->type = route->type;
527 monotime(&summary->changed);
528 }
529
530 summary->prefix_options = route->prefix_options;
531 summary->path.router_bits = route->path.router_bits;
532 summary->path.options[0] = route->path.options[0];
533 summary->path.options[1] = route->path.options[1];
534 summary->path.options[2] = route->path.options[2];
535 summary->path.area_id = area->area_id;
536 summary->path.type = OSPF6_PATH_TYPE_INTER;
537 summary->path.subtype = route->path.subtype;
538 summary->path.cost = route->path.cost;
539 /* summary->nexthop[0] = route->nexthop[0]; */
540
541 /* prepare buffer */
542 memset(buffer, 0, sizeof(buffer));
543 lsa_header = (struct ospf6_lsa_header *)buffer;
544
545 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
546 router_lsa = (struct ospf6_inter_router_lsa
547 *)((caddr_t)lsa_header
548 + sizeof(struct ospf6_lsa_header));
549 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
550
551 /* Fill Inter-Area-Router-LSA */
552 router_lsa->options[0] = route->path.options[0];
553 router_lsa->options[1] = route->path.options[1];
554 router_lsa->options[2] = route->path.options[2];
555 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
556 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
557 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
558 } else {
559 prefix_lsa = (struct ospf6_inter_prefix_lsa
560 *)((caddr_t)lsa_header
561 + sizeof(struct ospf6_lsa_header));
562 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
563
564 /* Fill Inter-Area-Prefix-LSA */
565 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
566 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
567 prefix_lsa->prefix.prefix_options = route->prefix_options;
568
569 /* set Prefix */
570 memcpy(p, &route->prefix.u.prefix6,
571 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
572 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
573 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
574 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
575 }
576
577 /* Fill LSA Header */
578 lsa_header->age = 0;
579 lsa_header->type = type;
580 lsa_header->id = summary->path.origin.id;
581 lsa_header->adv_router = area->ospf6->router_id;
582 lsa_header->seqnum =
583 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
584 lsa_header->adv_router, area->lsdb);
585 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
586
587 /* LSA checksum */
588 ospf6_lsa_checksum(lsa_header);
589
590 /* create LSA */
591 lsa = ospf6_lsa_create(lsa_header);
592
593 /* Reset the unapproved flag */
594 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
595
596 /* Originate */
597 ospf6_lsa_originate_area(lsa, area);
598
599 if (IS_OSPF6_DEBUG_ABR)
600 zlog_debug("%s : finish area %s", __func__, area->name);
601
602 return 1;
603 }
604
605 void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
606 {
607 struct listnode *node, *nnode;
608 struct ospf6_area *oa;
609 struct ospf6_route *range;
610
611 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
612 for (range = ospf6_route_head(oa->range_table); range;
613 range = ospf6_route_next(range))
614 OSPF6_ABR_RANGE_CLEAR_COST(range);
615 for (range = ospf6_route_head(oa->nssa_range_table); range;
616 range = ospf6_route_next(range))
617 OSPF6_ABR_RANGE_CLEAR_COST(range);
618 }
619 }
620
621 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
622 struct ospf6 *o)
623 {
624 struct ospf6_route *ro;
625 uint32_t cost = 0;
626
627 for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
628 ro = ospf6_route_match_next(&range->prefix, ro)) {
629 if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
630 continue;
631 if (ro->path.area_id != range->path.area_id)
632 continue;
633 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
634 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
635 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
636 continue;
637 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
638 && ro->path.type != OSPF6_PATH_TYPE_INTRA)
639 continue;
640
641 cost = MAX(cost, ro->path.cost);
642 }
643
644 return cost;
645 }
646
647 static inline int
648 ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
649 {
650 int redo_summary = 0;
651
652 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
653 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
654 redo_summary = 1;
655 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
656 if (range->path.cost != 0) {
657 range->path.cost = 0;
658 redo_summary = 1;
659 }
660 } else if (cost) {
661 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
662 && range->path.cost != range->path.u.cost_config)) {
663 range->path.cost = range->path.u.cost_config;
664 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
665 redo_summary = 1;
666 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
667 && range->path.cost != cost) {
668 range->path.cost = cost;
669 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
670 redo_summary = 1;
671 }
672 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
673 /* Cost is zero, meaning no active range */
674 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
675 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
676 redo_summary = 1;
677 }
678
679 return (redo_summary);
680 }
681
682 void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
683 {
684 uint32_t cost = 0;
685 struct listnode *node, *nnode;
686 struct ospf6_area *oa;
687 int summary_orig = 0;
688
689 assert(range->type == OSPF6_DEST_TYPE_RANGE);
690 oa = ospf6_area_lookup(range->path.area_id, ospf6);
691 assert(oa);
692
693 /* update range's cost and active flag */
694 cost = ospf6_abr_range_compute_cost(range, ospf6);
695
696 if (IS_OSPF6_DEBUG_ABR)
697 zlog_debug("%s: range %pFX, cost %d", __func__, &range->prefix,
698 cost);
699
700 /* Non-zero cost is a proxy for active longer prefixes in this range.
701 * If there are active routes covered by this range AND either the
702 * configured
703 * cost has changed or the summarized cost has changed then redo
704 * summaries.
705 * Alternately, if there are no longer active prefixes and there are
706 * summary announcements, withdraw those announcements.
707 *
708 * The don't advertise code relies on the path.cost being set to UNSPEC
709 * to
710 * work the first time. Subsequent times the path.cost is not 0 anyway
711 * if there
712 * were active ranges.
713 */
714 if (!ospf6_abr_range_summary_needs_update(range, cost))
715 return;
716
717 if (IS_OSPF6_DEBUG_ABR)
718 zlog_debug("%s: range %pFX update", __func__, &range->prefix);
719
720 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
721 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
722 && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
723 ospf6_nssa_lsa_originate(range, oa, true);
724 summary_orig = 1;
725 } else {
726 struct ospf6_lsa *lsa;
727
728 lsa = ospf6_lsdb_lookup(range->path.origin.type,
729 range->path.origin.id,
730 ospf6->router_id, oa->lsdb);
731 if (lsa)
732 ospf6_lsa_premature_aging(lsa);
733 }
734 } else {
735 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
736 summary_orig +=
737 ospf6_abr_originate_summary_to_area(range, oa);
738 }
739 }
740
741 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
742 && summary_orig) {
743 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
744 if (IS_OSPF6_DEBUG_ABR)
745 zlog_debug("Add discard route");
746
747 ospf6_zebra_add_discard(range, ospf6);
748 }
749 } else {
750 /* Summary removed or no summary generated as no
751 * specifics exist */
752 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
753 if (IS_OSPF6_DEBUG_ABR)
754 zlog_debug("Delete discard route");
755
756 ospf6_zebra_delete_discard(range, ospf6);
757 }
758 }
759 }
760
761 void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
762 {
763 struct listnode *node, *nnode;
764 struct ospf6_area *oa;
765 struct ospf6_route *range = NULL;
766
767 if (IS_OSPF6_DEBUG_ABR) {
768 char buf[BUFSIZ];
769
770 if (route->type == OSPF6_DEST_TYPE_ROUTER)
771 inet_ntop(AF_INET,
772 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
773 sizeof(buf));
774 else
775 prefix2str(&route->prefix, buf, sizeof(buf));
776
777 zlog_debug("%s: route %s", __func__, buf);
778 }
779
780 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
781 oa = ospf6_area_lookup(route->path.area_id, ospf6);
782 if (!oa) {
783 zlog_err("OSPFv6 area lookup failed");
784 return;
785 }
786
787 range = ospf6_route_lookup_bestmatch(&route->prefix,
788 oa->range_table);
789 if (range) {
790 ospf6_abr_range_update(range, ospf6);
791 }
792 }
793
794 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
795 ospf6_abr_originate_summary_to_area(route, oa);
796 }
797
798 void ospf6_abr_defaults_to_stub(struct ospf6 *o)
799 {
800 struct listnode *node, *nnode;
801 struct ospf6_area *oa;
802 struct ospf6_route *def, *route;
803 int type = DEFAULT_ROUTE;
804
805 if (!o->backbone)
806 return;
807
808 def = ospf6_route_create(o);
809 def->type = OSPF6_DEST_TYPE_NETWORK;
810 def->prefix.family = AF_INET6;
811 def->prefix.prefixlen = 0;
812 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
813 def->type = OSPF6_DEST_TYPE_NETWORK;
814 def->path.type = OSPF6_PATH_TYPE_INTER;
815 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
816 def->path.area_id = o->backbone->area_id;
817 def->path.metric_type = metric_type(o, type, 0);
818 def->path.cost = metric_value(o, type, 0);
819
820 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
821 if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
822 /* announce defaults to stubby areas */
823 if (IS_OSPF6_DEBUG_ABR)
824 zlog_debug(
825 "Announcing default route into stubby area %s",
826 oa->name);
827 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
828 ospf6_abr_originate_summary_to_area(def, oa);
829 } else {
830 /* withdraw defaults when an area switches from stub to
831 * non-stub */
832 route = ospf6_route_lookup(&def->prefix,
833 oa->summary_prefix);
834 if (route
835 && (route->path.subtype == def->path.subtype)) {
836 if (IS_OSPF6_DEBUG_ABR)
837 zlog_debug(
838 "Withdrawing default route from non-stubby area %s",
839 oa->name);
840 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
841 ospf6_abr_originate_summary_to_area(def, oa);
842 }
843 }
844 }
845 ospf6_route_delete(def);
846 }
847
848 void ospf6_abr_old_path_update(struct ospf6_route *old_route,
849 struct ospf6_route *route,
850 struct ospf6_route_table *table)
851 {
852 struct ospf6_path *o_path = NULL;
853 struct listnode *anode, *anext;
854 struct listnode *nnode, *rnode, *rnext;
855 struct ospf6_nexthop *nh, *rnh;
856
857 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
858 if (o_path->area_id != route->path.area_id
859 || !ospf6_ls_origin_same(o_path, &route->path))
860 continue;
861
862 if ((o_path->cost == route->path.cost) &&
863 (o_path->u.cost_e2 == route->path.u.cost_e2))
864 continue;
865
866 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
867 for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
868 rnext, rnh)) {
869 if (!ospf6_nexthop_is_same(rnh, nh))
870 continue;
871 listnode_delete(old_route->nh_list, rnh);
872 ospf6_nexthop_delete(rnh);
873 }
874
875 }
876
877 listnode_delete(old_route->paths, o_path);
878 ospf6_path_free(o_path);
879
880 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
881 anext, o_path)) {
882 ospf6_merge_nexthops(old_route->nh_list,
883 o_path->nh_list);
884 }
885
886 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
887 zlog_debug("%s: paths %u nh %u", __func__,
888 old_route->paths
889 ? listcount(old_route->paths)
890 : 0,
891 old_route->nh_list
892 ? listcount(old_route->nh_list)
893 : 0);
894
895 if (table->hook_add)
896 (*table->hook_add)(old_route);
897
898 if (old_route->path.origin.id == route->path.origin.id &&
899 old_route->path.origin.adv_router ==
900 route->path.origin.adv_router) {
901 struct ospf6_path *h_path;
902
903 h_path = (struct ospf6_path *)
904 listgetdata(listhead(old_route->paths));
905 old_route->path.origin.type = h_path->origin.type;
906 old_route->path.origin.id = h_path->origin.id;
907 old_route->path.origin.adv_router =
908 h_path->origin.adv_router;
909 }
910 }
911 }
912
913 void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
914 struct ospf6_route_table *table)
915 {
916 if (IS_OSPF6_DEBUG_ABR)
917 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
918 listcount(old->paths));
919
920 if (listcount(old->paths) > 1) {
921 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
922 struct ospf6_path *o_path;
923 struct ospf6_nexthop *nh, *rnh;
924 bool nh_updated = false;
925
926 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
927 if (o_path->origin.adv_router != lsa->header->adv_router
928 || o_path->origin.id != lsa->header->id)
929 continue;
930 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
931 for (ALL_LIST_ELEMENTS(old->nh_list,
932 rnode, rnext, rnh)) {
933 if (!ospf6_nexthop_is_same(rnh, nh))
934 continue;
935 if (IS_OSPF6_DEBUG_ABR)
936 zlog_debug("deleted nexthop");
937 listnode_delete(old->nh_list, rnh);
938 ospf6_nexthop_delete(rnh);
939 }
940 }
941 listnode_delete(old->paths, o_path);
942 ospf6_path_free(o_path);
943 nh_updated = true;
944 }
945
946 if (nh_updated) {
947 if (listcount(old->paths)) {
948 if (IS_OSPF6_DEBUG_ABR
949 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
950 zlog_debug("%s: old %pFX updated nh %u",
951 __func__, &old->prefix,
952 old->nh_list ? listcount(
953 old->nh_list)
954 : 0);
955
956 if (table->hook_add)
957 (*table->hook_add)(old);
958
959 if ((old->path.origin.id == lsa->header->id) &&
960 (old->path.origin.adv_router
961 == lsa->header->adv_router)) {
962 struct ospf6_path *h_path;
963
964 h_path = (struct ospf6_path *)
965 listgetdata(
966 listhead(old->paths));
967 old->path.origin.type =
968 h_path->origin.type;
969 old->path.origin.id = h_path->origin.id;
970 old->path.origin.adv_router =
971 h_path->origin.adv_router;
972 }
973 } else
974 ospf6_route_remove(old, table);
975 }
976 } else
977 ospf6_route_remove(old, table);
978 }
979
980 /* RFC 2328 16.2. Calculating the inter-area routes */
981 void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
982 {
983 struct prefix prefix, abr_prefix;
984 struct ospf6_route_table *table = NULL;
985 struct ospf6_route *range, *route, *old = NULL, *old_route;
986 struct ospf6_route *abr_entry;
987 uint8_t type = 0;
988 char options[3] = {0, 0, 0};
989 uint8_t prefix_options = 0;
990 uint32_t cost = 0;
991 uint8_t router_bits = 0;
992 char buf[PREFIX2STR_BUFFER];
993 int is_debug = 0;
994 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
995 struct ospf6_inter_router_lsa *router_lsa = NULL;
996 bool old_entry_updated = false;
997 struct ospf6_path *path, *o_path, *ecmp_path;
998 struct listnode *anode;
999 bool add_route = false;
1000
1001 memset(&prefix, 0, sizeof(prefix));
1002
1003 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1004 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
1005 is_debug++;
1006 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1007 lsa->name, ospf6_lsa_age_current(lsa),
1008 oa->name);
1009 }
1010
1011 prefix_lsa =
1012 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1013 lsa->header);
1014 prefix.family = AF_INET6;
1015 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
1016 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
1017 &prefix_lsa->prefix);
1018 if (is_debug)
1019 prefix2str(&prefix, buf, sizeof(buf));
1020 table = oa->ospf6->route_table;
1021 type = OSPF6_DEST_TYPE_NETWORK;
1022 prefix_options = prefix_lsa->prefix.prefix_options;
1023 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
1024 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1025 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
1026 is_debug++;
1027 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1028 lsa->name, ospf6_lsa_age_current(lsa),
1029 oa->name);
1030 }
1031
1032 router_lsa =
1033 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1034 lsa->header);
1035 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
1036 &prefix);
1037 if (is_debug)
1038 inet_ntop(AF_INET, &router_lsa->router_id, buf,
1039 sizeof(buf));
1040
1041 table = oa->ospf6->brouter_table;
1042 type = OSPF6_DEST_TYPE_ROUTER;
1043 options[0] = router_lsa->options[0];
1044 options[1] = router_lsa->options[1];
1045 options[2] = router_lsa->options[2];
1046 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
1047 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
1048 } else
1049 assert(0);
1050
1051 /* Find existing route */
1052 route = ospf6_route_lookup(&prefix, table);
1053 if (route) {
1054 ospf6_route_lock(route);
1055 if (is_debug)
1056 zlog_debug("%s: route %pFX, paths %d", __func__,
1057 &prefix, listcount(route->paths));
1058 }
1059 while (route && ospf6_route_is_prefix(&prefix, route)) {
1060 if (route->path.area_id == oa->area_id
1061 && route->path.origin.type == lsa->header->type
1062 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
1063 /* LSA adv. router could be part of route's
1064 * paths list. Find the existing path and set
1065 * old as the route.
1066 */
1067 if (listcount(route->paths) > 1) {
1068 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
1069 o_path)) {
1070 if (o_path->origin.id == lsa->header->id
1071 && o_path->origin.adv_router ==
1072 lsa->header->adv_router) {
1073 old = route;
1074
1075 if (is_debug)
1076 zlog_debug(
1077 "%s: old entry found in paths, adv_router %pI4",
1078 __func__,
1079 &o_path->origin.adv_router);
1080
1081 break;
1082 }
1083 }
1084 } else if (route->path.origin.id == lsa->header->id &&
1085 route->path.origin.adv_router ==
1086 lsa->header->adv_router)
1087 old = route;
1088 }
1089 route = ospf6_route_next(route);
1090 }
1091 if (route)
1092 ospf6_route_unlock(route);
1093
1094 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1095 if (cost == OSPF_LS_INFINITY) {
1096 if (is_debug)
1097 zlog_debug("cost is LS_INFINITY, ignore");
1098 if (old)
1099 ospf6_abr_old_route_remove(lsa, old, table);
1100 return;
1101 }
1102 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
1103 if (is_debug)
1104 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
1105 lsa->name);
1106 if (old)
1107 ospf6_abr_old_route_remove(lsa, old, table);
1108 return;
1109 }
1110
1111
1112 /* (2) if the LSA is self-originated, ignore */
1113 if (lsa->header->adv_router == oa->ospf6->router_id) {
1114 if (is_debug)
1115 zlog_debug("LSA %s is self-originated, ignore",
1116 lsa->name);
1117 if (old)
1118 ospf6_route_remove(old, table);
1119 return;
1120 }
1121
1122 /* (3) if the prefix is equal to an active configured address range */
1123 /* or if the NU bit is set in the prefix */
1124 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1125 /* must have been set in previous block */
1126 assert(prefix_lsa);
1127
1128 range = ospf6_route_lookup(&prefix, oa->range_table);
1129 if (range) {
1130 if (is_debug)
1131 zlog_debug(
1132 "Prefix is equal to address range, ignore");
1133 if (old)
1134 ospf6_route_remove(old, table);
1135 return;
1136 }
1137
1138 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1139 OSPF6_PREFIX_OPTION_NU)
1140 || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1141 OSPF6_PREFIX_OPTION_LA)) {
1142 if (is_debug)
1143 zlog_debug("Prefix has NU/LA bit set, ignore");
1144 if (old)
1145 ospf6_route_remove(old, table);
1146 return;
1147 }
1148 }
1149
1150 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1151 /* To pass test suites */
1152 assert(router_lsa);
1153 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
1154 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
1155 if (is_debug)
1156 zlog_debug("Prefix has NU/LA bit set, ignore");
1157 if (old)
1158 ospf6_route_remove(old, table);
1159
1160 return;
1161 }
1162 /* Avoid infinite recursion if someone has maliciously announced
1163 an
1164 Inter-Router LSA for an ABR
1165 */
1166 if (lsa->header->adv_router == router_lsa->router_id) {
1167 if (is_debug)
1168 zlog_debug(
1169 "Ignoring Inter-Router LSA for an ABR (%s)",
1170 buf);
1171 if (old)
1172 ospf6_route_remove(old, table);
1173
1174 return;
1175 }
1176 }
1177
1178 /* (4) if the routing table entry for the ABR does not exist */
1179 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
1180 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
1181 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
1182 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
1183 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
1184 if (is_debug)
1185 zlog_debug(
1186 "%s: ABR router entry %pFX does not exist, ignore",
1187 __func__, &abr_prefix);
1188 if (old) {
1189 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
1190 oa->intra_brouter_calc) {
1191 if (is_debug)
1192 zlog_debug(
1193 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1194 __func__, buf, (void *)old);
1195 } else {
1196 if (is_debug)
1197 zlog_debug(
1198 "%s: remove old entry: %s %p ",
1199 __func__, buf, (void *)old);
1200 ospf6_abr_old_route_remove(lsa, old, table);
1201 }
1202 }
1203 return;
1204 }
1205
1206 /* (5),(6): the path preference is handled by the sorting
1207 in the routing table. Always install the path by substituting
1208 old route (if any). */
1209 route = ospf6_route_create(oa->ospf6);
1210
1211 route->type = type;
1212 route->prefix = prefix;
1213 route->prefix_options = prefix_options;
1214 route->path.origin.type = lsa->header->type;
1215 route->path.origin.id = lsa->header->id;
1216 route->path.origin.adv_router = lsa->header->adv_router;
1217 route->path.router_bits = router_bits;
1218 route->path.options[0] = options[0];
1219 route->path.options[1] = options[1];
1220 route->path.options[2] = options[2];
1221 route->path.area_id = oa->area_id;
1222 route->path.type = OSPF6_PATH_TYPE_INTER;
1223 route->path.cost = abr_entry->path.cost + cost;
1224
1225 /* copy brouter rechable nexthops into the route. */
1226 ospf6_route_copy_nexthops(route, abr_entry);
1227
1228 /* (7) If the routes are identical, copy the next hops over to existing
1229 route. ospf6's route table implementation will otherwise string both
1230 routes, but keep the older one as the best route since the routes
1231 are identical.
1232 */
1233 old = ospf6_route_lookup(&prefix, table);
1234 if (old) {
1235 if (is_debug)
1236 zlog_debug("%s: found old route %pFX, paths %d",
1237 __func__, &prefix, listcount(old->paths));
1238 }
1239 for (old_route = old; old_route; old_route = old_route->next) {
1240
1241 /* The route linked-list is grouped in batches of prefix.
1242 * If the new prefix is not the same as the one of interest
1243 * then we have walked over the end of the batch and so we
1244 * should break rather than continuing unnecessarily.
1245 */
1246 if (!ospf6_route_is_same(old_route, route))
1247 break;
1248 if ((old_route->type != route->type)
1249 || (old_route->path.type != route->path.type))
1250 continue;
1251
1252 if ((ospf6_route_cmp(route, old_route) != 0)) {
1253 if (is_debug)
1254 zlog_debug(
1255 "%s: old %p %pFX cost %u new route cost %u are not same",
1256 __func__, (void *)old_route, &prefix,
1257 old_route->path.cost, route->path.cost);
1258
1259 /* Check new route's adv. router is same in one of
1260 * the paths with differed cost, if so remove the
1261 * old path as later new route will be added.
1262 */
1263 if (listcount(old_route->paths) > 1)
1264 ospf6_abr_old_path_update(old_route, route,
1265 table);
1266 continue;
1267 }
1268
1269 list_delete_all_node(old_route->nh_list);
1270 ospf6_route_copy_nexthops(old_route, route);
1271 old_entry_updated = true;
1272
1273 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1274 o_path)) {
1275 if (o_path->area_id == route->path.area_id
1276 && ospf6_ls_origin_same(o_path, &route->path))
1277 break;
1278 }
1279
1280 /* New adv. router for a existing path add to paths list */
1281 if (o_path == NULL) {
1282 ecmp_path = ospf6_path_dup(&route->path);
1283
1284 /* Add a nh_list to new ecmp path */
1285 ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
1286
1287 /* Add the new path to route's path list */
1288 listnode_add_sort(old_route->paths, ecmp_path);
1289
1290 if (is_debug) {
1291 zlog_debug(
1292 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1293 __func__, &route->prefix,
1294 old_route->path.cost,
1295 &ecmp_path->origin.adv_router,
1296 listcount(ecmp_path->nh_list),
1297 old_route->paths
1298 ? listcount(old_route->paths)
1299 : 0,
1300 listcount(old_route->nh_list));
1301 }
1302 } else {
1303 struct ospf6_route *tmp_route;
1304
1305 tmp_route = ospf6_route_create(oa->ospf6);
1306
1307 ospf6_copy_nexthops(tmp_route->nh_list,
1308 o_path->nh_list);
1309
1310 if (!ospf6_route_cmp_nexthops(tmp_route, route)) {
1311 /* adv. router exists in the list, update nhs */
1312 list_delete_all_node(o_path->nh_list);
1313 ospf6_copy_nexthops(o_path->nh_list,
1314 route->nh_list);
1315 ospf6_route_delete(tmp_route);
1316 } else {
1317 /* adv. router has no change in nhs */
1318 old_entry_updated = false;
1319 ospf6_route_delete(tmp_route);
1320 continue;
1321 }
1322 }
1323
1324 if (is_debug)
1325 zlog_debug(
1326 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1327 __func__, buf, (void *)old_route,
1328 old_route->path.cost, route->path.cost,
1329 listcount(old_route->nh_list));
1330
1331 /* For Inter-Prefix route: Update RIB/FIB,
1332 * For Inter-Router trigger summary update
1333 */
1334 if (table->hook_add)
1335 (*table->hook_add)(old_route);
1336
1337 break;
1338 }
1339
1340 /* If the old entry is not updated and old entry not found or old entry
1341 * does not match with the new entry then add the new route
1342 */
1343 if (old_entry_updated == false) {
1344 if ((old == NULL) || (old->type != route->type)
1345 || (old->path.type != route->path.type)
1346 || (old->path.cost != route->path.cost))
1347 add_route = true;
1348 }
1349
1350 if (add_route) {
1351 if (is_debug) {
1352 zlog_debug(
1353 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1354 __func__, buf, route->path.cost,
1355 listcount(route->nh_list),
1356 &route->path.origin.adv_router);
1357 }
1358
1359 path = ospf6_path_dup(&route->path);
1360 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
1361 listnode_add_sort(route->paths, path);
1362 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1363 ospf6_route_add(route, table);
1364 } else
1365 /* if we did not add the route remove it */
1366 ospf6_route_delete(route);
1367 }
1368
1369 void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
1370 struct ospf6 *ospf6)
1371 {
1372 struct ospf6_lsa *lsa;
1373 struct ospf6_area *oa;
1374 uint16_t type;
1375
1376 oa = ospf6_area_lookup(route->path.area_id, ospf6);
1377 /*
1378 * It is possible to designate a non backbone
1379 * area first. If that is the case safely
1380 * fall out of this function.
1381 */
1382 if (oa == NULL)
1383 return;
1384
1385 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1386 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1387 ospf6_abr_examin_summary(lsa, oa);
1388
1389 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1390 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1391 ospf6_abr_examin_summary(lsa, oa);
1392 }
1393
1394 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
1395 {
1396 struct ospf6_route *route;
1397
1398 if (IS_OSPF6_DEBUG_ABR)
1399 zlog_debug("Re-examining Inter-Prefix Summaries");
1400
1401 for (route = ospf6_route_head(o->route_table); route;
1402 route = ospf6_route_next(route))
1403 ospf6_abr_originate_summary(route, o);
1404
1405 if (IS_OSPF6_DEBUG_ABR)
1406 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1407 }
1408
1409
1410 /* Display functions */
1411 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1412 char *buf, int buflen,
1413 int pos)
1414 {
1415 struct ospf6_inter_prefix_lsa *prefix_lsa;
1416 struct in6_addr in6;
1417 char tbuf[16];
1418
1419 if (lsa != NULL) {
1420 prefix_lsa =
1421 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1422 lsa->header);
1423
1424 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
1425 if (buf) {
1426 inet_ntop(AF_INET6, &in6, buf, buflen);
1427 snprintf(tbuf, sizeof(tbuf), "/%d",
1428 prefix_lsa->prefix.prefix_length);
1429 strlcat(buf, tbuf, buflen);
1430 }
1431 }
1432
1433 return (buf);
1434 }
1435
1436 static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1437 struct ospf6_lsa *lsa,
1438 json_object *json_obj,
1439 bool use_json)
1440 {
1441 struct ospf6_inter_prefix_lsa *prefix_lsa;
1442 char buf[INET6_ADDRSTRLEN];
1443
1444 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1445 lsa->header);
1446
1447 if (use_json) {
1448 json_object_int_add(
1449 json_obj, "metric",
1450 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1451 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1452 buf, sizeof(buf));
1453 json_object_string_add(json_obj, "prefixOptions", buf);
1454 json_object_string_add(
1455 json_obj, "prefix",
1456 ospf6_inter_area_prefix_lsa_get_prefix_str(
1457 lsa, buf, sizeof(buf), 0));
1458 } else {
1459 vty_out(vty, " Metric: %lu\n",
1460 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1461
1462 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1463 buf, sizeof(buf));
1464 vty_out(vty, " Prefix Options: %s\n", buf);
1465
1466 vty_out(vty, " Prefix: %s\n",
1467 ospf6_inter_area_prefix_lsa_get_prefix_str(
1468 lsa, buf, sizeof(buf), 0));
1469 }
1470
1471 return 0;
1472 }
1473
1474 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1475 char *buf, int buflen,
1476 int pos)
1477 {
1478 struct ospf6_inter_router_lsa *router_lsa;
1479
1480 if (lsa != NULL) {
1481 router_lsa =
1482 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1483 lsa->header);
1484
1485
1486 if (buf)
1487 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1488 }
1489
1490 return (buf);
1491 }
1492
1493 static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1494 struct ospf6_lsa *lsa,
1495 json_object *json_obj,
1496 bool use_json)
1497 {
1498 struct ospf6_inter_router_lsa *router_lsa;
1499 char buf[64];
1500
1501 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1502 lsa->header);
1503
1504 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1505 if (use_json) {
1506 json_object_string_add(json_obj, "options", buf);
1507 json_object_int_add(
1508 json_obj, "metric",
1509 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1510 } else {
1511 vty_out(vty, " Options: %s\n", buf);
1512 vty_out(vty, " Metric: %lu\n",
1513 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1514 }
1515
1516 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1517 if (use_json)
1518 json_object_string_add(json_obj, "destinationRouterId", buf);
1519 else
1520 vty_out(vty, " Destination Router ID: %s\n", buf);
1521
1522 return 0;
1523 }
1524
1525 /* Debug commands */
1526 DEFUN (debug_ospf6_abr,
1527 debug_ospf6_abr_cmd,
1528 "debug ospf6 abr",
1529 DEBUG_STR
1530 OSPF6_STR
1531 "Debug OSPFv3 ABR function\n"
1532 )
1533 {
1534 OSPF6_DEBUG_ABR_ON();
1535 return CMD_SUCCESS;
1536 }
1537
1538 DEFUN (no_debug_ospf6_abr,
1539 no_debug_ospf6_abr_cmd,
1540 "no debug ospf6 abr",
1541 NO_STR
1542 DEBUG_STR
1543 OSPF6_STR
1544 "Debug OSPFv3 ABR function\n"
1545 )
1546 {
1547 OSPF6_DEBUG_ABR_OFF();
1548 return CMD_SUCCESS;
1549 }
1550
1551 int config_write_ospf6_debug_abr(struct vty *vty)
1552 {
1553 if (IS_OSPF6_DEBUG_ABR)
1554 vty_out(vty, "debug ospf6 abr\n");
1555 return 0;
1556 }
1557
1558 void install_element_ospf6_debug_abr(void)
1559 {
1560 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1561 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1562 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1563 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1564 }
1565
1566 static struct ospf6_lsa_handler inter_prefix_handler = {
1567 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1568 .lh_name = "Inter-Prefix",
1569 .lh_short_name = "IAP",
1570 .lh_show = ospf6_inter_area_prefix_lsa_show,
1571 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
1572 .lh_debug = 0};
1573
1574 static struct ospf6_lsa_handler inter_router_handler = {
1575 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1576 .lh_name = "Inter-Router",
1577 .lh_short_name = "IAR",
1578 .lh_show = ospf6_inter_area_router_lsa_show,
1579 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
1580 .lh_debug = 0};
1581
1582 void ospf6_abr_init(void)
1583 {
1584 ospf6_install_lsa_handler(&inter_prefix_handler);
1585 ospf6_install_lsa_handler(&inter_router_handler);
1586 }