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