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