]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
doc: Add documentation for default-information originate.
[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;
c4122b55 649 int type = DEFAULT_ROUTE;
d62a17ae 650
651 if (!o->backbone)
652 return;
653
654 def = ospf6_route_create();
655 def->type = OSPF6_DEST_TYPE_NETWORK;
656 def->prefix.family = AF_INET6;
657 def->prefix.prefixlen = 0;
658 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
659 def->type = OSPF6_DEST_TYPE_NETWORK;
660 def->path.type = OSPF6_PATH_TYPE_INTER;
661 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
662 def->path.area_id = o->backbone->area_id;
c4122b55
YR
663 def->path.metric_type = metric_type(o, type, 0);
664 def->path.cost = metric_value(o, type, 0);
d62a17ae 665
beadc736 666 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
d62a17ae 667 if (!IS_AREA_STUB(oa)) {
668 /* withdraw defaults when an area switches from stub to
669 * non-stub */
670 route = ospf6_route_lookup(&def->prefix,
671 oa->summary_prefix);
672 if (route
673 && (route->path.subtype == def->path.subtype)) {
674 if (IS_OSPF6_DEBUG_ABR)
675 zlog_debug(
676 "Withdrawing default route from non-stubby area %s",
677 oa->name);
678 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
679 ospf6_abr_originate_summary_to_area(def, oa);
680 }
681 } else {
682 /* announce defaults to stubby areas */
683 if (IS_OSPF6_DEBUG_ABR)
684 zlog_debug(
685 "Announcing default route into stubby area %s",
686 oa->name);
687 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
688 ospf6_abr_originate_summary_to_area(def, oa);
689 }
ca1f4309 690 }
d62a17ae 691 ospf6_route_delete(def);
ca1f4309
DS
692}
693
6f19bb0e
CS
694void ospf6_abr_old_path_update(struct ospf6_route *old_route,
695 struct ospf6_route *route,
e285b70d 696 struct ospf6_route_table *table)
6f19bb0e
CS
697{
698 struct ospf6_path *o_path = NULL;
699 struct listnode *anode, *anext;
700 struct listnode *nnode, *rnode, *rnext;
701 struct ospf6_nexthop *nh, *rnh;
702
703 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
704 if (o_path->area_id != route->path.area_id ||
705 (memcmp(&(o_path)->origin, &(route)->path.origin,
706 sizeof(struct ospf6_ls_origin)) != 0))
707 continue;
708
709 if ((o_path->cost == route->path.cost) &&
710 (o_path->u.cost_e2 == route->path.u.cost_e2))
711 continue;
712
713 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
714 for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
715 rnext, rnh)) {
716 if (!ospf6_nexthop_is_same(rnh, nh))
717 continue;
718 listnode_delete(old_route->nh_list, rnh);
719 ospf6_nexthop_delete(rnh);
720 }
721
722 }
723
724 listnode_delete(old_route->paths, o_path);
725 ospf6_path_free(o_path);
726
727 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
728 anext, o_path)) {
729 ospf6_merge_nexthops(old_route->nh_list,
730 o_path->nh_list);
731 }
732
733 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
5e81f5dd
DS
734 zlog_debug("%s: paths %u nh %u", __func__,
735 old_route->paths
736 ? listcount(old_route->paths)
737 : 0,
738 old_route->nh_list
739 ? listcount(old_route->nh_list)
740 : 0);
6f19bb0e
CS
741
742 if (table->hook_add)
e285b70d 743 (*table->hook_add)(old_route);
6f19bb0e
CS
744
745 if (old_route->path.origin.id == route->path.origin.id &&
746 old_route->path.origin.adv_router ==
747 route->path.origin.adv_router) {
748 struct ospf6_path *h_path;
749
750 h_path = (struct ospf6_path *)
751 listgetdata(listhead(old_route->paths));
752 old_route->path.origin.type = h_path->origin.type;
753 old_route->path.origin.id = h_path->origin.id;
754 old_route->path.origin.adv_router =
755 h_path->origin.adv_router;
756 }
757 }
758}
759
beadc736 760void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
e285b70d 761 struct ospf6_route_table *table)
6f19bb0e 762{
b9b87bfc
S
763 if (IS_OSPF6_DEBUG_ABR)
764 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
765 listcount(old->paths));
766
6f19bb0e
CS
767 if (listcount(old->paths) > 1) {
768 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
769 struct ospf6_path *o_path;
770 struct ospf6_nexthop *nh, *rnh;
771 bool nh_updated = false;
6f19bb0e
CS
772
773 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
774 if (o_path->origin.adv_router != lsa->header->adv_router
b9b87bfc 775 || o_path->origin.id != lsa->header->id)
6f19bb0e
CS
776 continue;
777 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
778 for (ALL_LIST_ELEMENTS(old->nh_list,
779 rnode, rnext, rnh)) {
780 if (!ospf6_nexthop_is_same(rnh, nh))
781 continue;
b9b87bfc
S
782 if (IS_OSPF6_DEBUG_ABR)
783 zlog_debug("deleted nexthop");
6f19bb0e
CS
784 listnode_delete(old->nh_list, rnh);
785 ospf6_nexthop_delete(rnh);
786 }
787 }
788 listnode_delete(old->paths, o_path);
789 ospf6_path_free(o_path);
790 nh_updated = true;
791 }
792
793 if (nh_updated) {
794 if (listcount(old->paths)) {
2dbe669b
DA
795 if (IS_OSPF6_DEBUG_ABR
796 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
797 zlog_debug("%s: old %pFX updated nh %u",
798 __func__, &old->prefix,
5e81f5dd
DS
799 old->nh_list ? listcount(
800 old->nh_list)
801 : 0);
6f19bb0e
CS
802
803 if (table->hook_add)
e285b70d 804 (*table->hook_add)(old);
6f19bb0e
CS
805
806 if ((old->path.origin.id == lsa->header->id) &&
807 (old->path.origin.adv_router
808 == lsa->header->adv_router)) {
809 struct ospf6_path *h_path;
810
811 h_path = (struct ospf6_path *)
812 listgetdata(
813 listhead(old->paths));
814 old->path.origin.type =
815 h_path->origin.type;
816 old->path.origin.id = h_path->origin.id;
817 old->path.origin.adv_router =
818 h_path->origin.adv_router;
819 }
820 } else
e285b70d 821 ospf6_route_remove(old, table);
6f19bb0e
CS
822 }
823 } else
e285b70d 824 ospf6_route_remove(old, table);
6f19bb0e
CS
825}
826
049207c3 827/* RFC 2328 16.2. Calculating the inter-area routes */
d62a17ae 828void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
049207c3 829{
d62a17ae 830 struct prefix prefix, abr_prefix;
831 struct ospf6_route_table *table = NULL;
99ab28cb 832 struct ospf6_route *range, *route, *old = NULL, *old_route;
d62a17ae 833 struct ospf6_route *abr_entry;
d7c0a89a 834 uint8_t type = 0;
d62a17ae 835 char options[3] = {0, 0, 0};
d7c0a89a
QY
836 uint8_t prefix_options = 0;
837 uint32_t cost = 0;
838 uint8_t router_bits = 0;
d62a17ae 839 char buf[PREFIX2STR_BUFFER];
840 int is_debug = 0;
841 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
842 struct ospf6_inter_router_lsa *router_lsa = NULL;
99ab28cb 843 bool old_entry_updated = false;
6f19bb0e
CS
844 struct ospf6_path *path, *o_path, *ecmp_path;
845 struct listnode *anode;
b9b87bfc 846 bool add_route = false;
d62a17ae 847
848 memset(&prefix, 0, sizeof(prefix));
849
850 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
851 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
852 is_debug++;
b9b87bfc
S
853 zlog_debug("%s: LSA %s age %d in area %s", __func__,
854 lsa->name, ospf6_lsa_age_current(lsa),
855 oa->name);
d62a17ae 856 }
857
858 prefix_lsa =
859 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
860 lsa->header);
861 prefix.family = AF_INET6;
862 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
b8ce0c36 863 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
864 &prefix_lsa->prefix);
d62a17ae 865 if (is_debug)
866 prefix2str(&prefix, buf, sizeof(buf));
867 table = oa->ospf6->route_table;
868 type = OSPF6_DEST_TYPE_NETWORK;
869 prefix_options = prefix_lsa->prefix.prefix_options;
870 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
871 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
872 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
873 is_debug++;
b9b87bfc
S
874 zlog_debug("%s: LSA %s age %d in area %s", __func__,
875 lsa->name, ospf6_lsa_age_current(lsa),
876 oa->name);
d62a17ae 877 }
878
879 router_lsa =
880 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
881 lsa->header);
882 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
883 &prefix);
884 if (is_debug)
885 inet_ntop(AF_INET, &router_lsa->router_id, buf,
886 sizeof(buf));
887
888 table = oa->ospf6->brouter_table;
889 type = OSPF6_DEST_TYPE_ROUTER;
890 options[0] = router_lsa->options[0];
891 options[1] = router_lsa->options[1];
892 options[2] = router_lsa->options[2];
893 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
894 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
895 } else
896 assert(0);
897
898 /* Find existing route */
899 route = ospf6_route_lookup(&prefix, table);
b9b87bfc 900 if (route) {
d62a17ae 901 ospf6_route_lock(route);
b9b87bfc
S
902 if (is_debug)
903 zlog_debug("%s: route %pFX, paths %d", __func__,
904 &prefix, listcount(route->paths));
905 }
d62a17ae 906 while (route && ospf6_route_is_prefix(&prefix, route)) {
907 if (route->path.area_id == oa->area_id
908 && route->path.origin.type == lsa->header->type
6f19bb0e
CS
909 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
910 /* LSA adv. router could be part of route's
911 * paths list. Find the existing path and set
912 * old as the route.
913 */
914 if (listcount(route->paths) > 1) {
6f19bb0e
CS
915 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
916 o_path)) {
6f19bb0e
CS
917 if (o_path->origin.id == lsa->header->id
918 && o_path->origin.adv_router ==
919 lsa->header->adv_router) {
920 old = route;
921
922 if (is_debug)
5e81f5dd 923 zlog_debug(
dc138868 924 "%s: old entry found in paths, adv_router %pI4",
5e81f5dd 925 __func__,
dc138868 926 &o_path->origin.adv_router);
6f19bb0e
CS
927
928 break;
929 }
930 }
931 } else if (route->path.origin.id == lsa->header->id &&
932 route->path.origin.adv_router ==
933 lsa->header->adv_router)
934 old = route;
935 }
d62a17ae 936 route = ospf6_route_next(route);
937 }
938 if (route)
939 ospf6_route_unlock(route);
940
941 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
942 if (cost == OSPF_LS_INFINITY) {
943 if (is_debug)
944 zlog_debug("cost is LS_INFINITY, ignore");
945 if (old)
e285b70d 946 ospf6_abr_old_route_remove(lsa, old, table);
d62a17ae 947 return;
948 }
949 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
950 if (is_debug)
5e81f5dd
DS
951 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
952 lsa->name);
d62a17ae 953 if (old)
e285b70d 954 ospf6_abr_old_route_remove(lsa, old, table);
d62a17ae 955 return;
956 }
957
b9b87bfc 958
d62a17ae 959 /* (2) if the LSA is self-originated, ignore */
960 if (lsa->header->adv_router == oa->ospf6->router_id) {
961 if (is_debug)
6f19bb0e
CS
962 zlog_debug("LSA %s is self-originated, ignore",
963 lsa->name);
d62a17ae 964 if (old)
e285b70d 965 ospf6_route_remove(old, table);
d62a17ae 966 return;
01879114 967 }
d62a17ae 968
969 /* (3) if the prefix is equal to an active configured address range */
970 /* or if the NU bit is set in the prefix */
971 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
8934b81c
QY
972 /* must have been set in previous block */
973 assert(prefix_lsa);
974
d62a17ae 975 range = ospf6_route_lookup(&prefix, oa->range_table);
976 if (range) {
977 if (is_debug)
978 zlog_debug(
979 "Prefix is equal to address range, ignore");
980 if (old)
e285b70d 981 ospf6_route_remove(old, table);
d62a17ae 982 return;
983 }
984
985 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
986 OSPF6_PREFIX_OPTION_NU)
987 || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
988 OSPF6_PREFIX_OPTION_LA)) {
989 if (is_debug)
990 zlog_debug("Prefix has NU/LA bit set, ignore");
991 if (old)
e285b70d 992 ospf6_route_remove(old, table);
d62a17ae 993 return;
994 }
01879114 995 }
d62a17ae 996
997 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
998 /* To pass test suites */
554bfe88 999 assert(router_lsa);
d62a17ae 1000 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
1001 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
1002 if (is_debug)
1003 zlog_debug("Prefix has NU/LA bit set, ignore");
1004 if (old)
e285b70d 1005 ospf6_route_remove(old, table);
d62a17ae 1006
1007 return;
1008 }
1009 /* Avoid infinite recursion if someone has maliciously announced
1010 an
1011 Inter-Router LSA for an ABR
1012 */
1013 if (lsa->header->adv_router == router_lsa->router_id) {
1014 if (is_debug)
1015 zlog_debug(
1016 "Ignorning Inter-Router LSA for an ABR (%s)",
1017 buf);
1018 if (old)
e285b70d 1019 ospf6_route_remove(old, table);
d62a17ae 1020
1021 return;
1022 }
1023 }
1024
1025 /* (4) if the routing table entry for the ABR does not exist */
1026 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
1027 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
1028 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
1029 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
1030 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
1031 if (is_debug)
5e81f5dd 1032 zlog_debug(
b9b87bfc
S
1033 "%s: ABR router entry %pFX does not exist, ignore",
1034 __func__, &abr_prefix);
a2d0055a
CS
1035 if (old) {
1036 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
1037 oa->intra_brouter_calc) {
1038 if (is_debug)
1039 zlog_debug(
5e81f5dd
DS
1040 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1041 __func__, buf, (void *)old);
a2d0055a
CS
1042 } else {
1043 if (is_debug)
5e81f5dd
DS
1044 zlog_debug(
1045 "%s: remove old entry: %s %p ",
1046 __func__, buf, (void *)old);
b9b87bfc 1047 ospf6_abr_old_route_remove(lsa, old, table);
a2d0055a
CS
1048 }
1049 }
d62a17ae 1050 return;
1051 }
1052
1053 /* Check import list */
1054 if (IMPORT_NAME(oa)) {
1055 if (IMPORT_LIST(oa) == NULL)
1056 IMPORT_LIST(oa) =
1057 access_list_lookup(AFI_IP6, IMPORT_NAME(oa));
1058
1059 if (IMPORT_LIST(oa))
1060 if (access_list_apply(IMPORT_LIST(oa), &prefix)
1061 == FILTER_DENY) {
1062 if (is_debug)
1063 zlog_debug(
1064 "Prefix was denied by import-list");
1065 if (old)
e285b70d 1066 ospf6_route_remove(old, table);
d62a17ae 1067 return;
1068 }
1069 }
1070
1071 /* Check input prefix-list */
6f19bb0e 1072 if (PREFIX_LIST_IN(oa)) {
427f8e61
DL
1073 if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
1074 != PREFIX_PERMIT) {
1075 if (is_debug)
996c9314 1076 zlog_debug("Prefix was denied by prefix-list");
427f8e61 1077 if (old)
e285b70d 1078 ospf6_route_remove(old, table);
427f8e61
DL
1079 return;
1080 }
6f19bb0e 1081 }
d62a17ae 1082
1083 /* (5),(6): the path preference is handled by the sorting
1084 in the routing table. Always install the path by substituting
1085 old route (if any). */
6f19bb0e 1086 route = ospf6_route_create();
d62a17ae 1087
1088 route->type = type;
1089 route->prefix = prefix;
1090 route->path.origin.type = lsa->header->type;
1091 route->path.origin.id = lsa->header->id;
1092 route->path.origin.adv_router = lsa->header->adv_router;
1093 route->path.router_bits = router_bits;
1094 route->path.options[0] = options[0];
1095 route->path.options[1] = options[1];
1096 route->path.options[2] = options[2];
1097 route->path.prefix_options = prefix_options;
1098 route->path.area_id = oa->area_id;
1099 route->path.type = OSPF6_PATH_TYPE_INTER;
1100 route->path.cost = abr_entry->path.cost + cost;
1101
6f19bb0e
CS
1102 /* copy brouter rechable nexthops into the route. */
1103 ospf6_route_copy_nexthops(route, abr_entry);
064d4355 1104
d62a17ae 1105 /* (7) If the routes are identical, copy the next hops over to existing
1106 route. ospf6's route table implementation will otherwise string both
1107 routes, but keep the older one as the best route since the routes
1108 are identical.
1109 */
1110 old = ospf6_route_lookup(&prefix, table);
b9b87bfc
S
1111 if (old) {
1112 if (is_debug)
1113 zlog_debug("%s: found old route %pFX, paths %d",
1114 __func__, &prefix, listcount(old->paths));
1115 }
99ab28cb
CS
1116 for (old_route = old; old_route; old_route = old_route->next) {
1117 if (!ospf6_route_is_same(old_route, route) ||
1118 (old_route->type != route->type) ||
1119 (old_route->path.type != route->path.type))
1120 continue;
064d4355 1121
99ab28cb 1122 if ((ospf6_route_cmp(route, old_route) != 0)) {
2dbe669b 1123 if (is_debug)
5e81f5dd 1124 zlog_debug(
2dbe669b
DA
1125 "%s: old %p %pFX cost %u new route cost %u are not same",
1126 __func__, (void *)old_route, &prefix,
5e81f5dd 1127 old_route->path.cost, route->path.cost);
6f19bb0e
CS
1128
1129 /* Check new route's adv. router is same in one of
1130 * the paths with differed cost, if so remove the
1131 * old path as later new route will be added.
1132 */
1133 if (listcount(old_route->paths) > 1)
1134 ospf6_abr_old_path_update(old_route, route,
e285b70d 1135 table);
99ab28cb
CS
1136 continue;
1137 }
1138
6f19bb0e 1139 ospf6_route_merge_nexthops(old_route, route);
99ab28cb 1140 old_entry_updated = true;
6f19bb0e
CS
1141
1142 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1143 o_path)) {
1144 if (o_path->area_id == route->path.area_id &&
1145 (memcmp(&(o_path)->origin, &(route)->path.origin,
1146 sizeof(struct ospf6_ls_origin)) == 0))
1147 break;
1148 }
1149
1150 /* New adv. router for a existing path add to paths list */
1151 if (o_path == NULL) {
1152 ecmp_path = ospf6_path_dup(&route->path);
1153
1154 /* Add a nh_list to new ecmp path */
1155 ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
1156
1157 /* Add the new path to route's path list */
1158 listnode_add_sort(old_route->paths, ecmp_path);
1159
1160 if (is_debug) {
5e81f5dd 1161 zlog_debug(
dc138868
DL
1162 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1163 __func__, &route->prefix,
1164 old_route->path.cost,
1165 &ecmp_path->origin.adv_router,
5e81f5dd
DS
1166 listcount(ecmp_path->nh_list),
1167 old_route->paths
1168 ? listcount(old_route->paths)
1169 : 0,
1170 listcount(old_route->nh_list));
6f19bb0e
CS
1171 }
1172 } else {
14ff96e6
DS
1173 struct ospf6_route *tmp_route = ospf6_route_create();
1174
1175 ospf6_copy_nexthops(tmp_route->nh_list,
1176 o_path->nh_list);
1177
1178 if (ospf6_route_cmp_nexthops(tmp_route, route) != 0) {
1179 /* adv. router exists in the list, update nhs */
1180 list_delete_all_node(o_path->nh_list);
1181 ospf6_copy_nexthops(o_path->nh_list,
1182 route->nh_list);
1183 ospf6_route_delete(tmp_route);
1184 } else {
1185 /* adv. router has no change in nhs */
1186 old_entry_updated = false;
1187 ospf6_route_delete(tmp_route);
1188 continue;
1189 }
6f19bb0e
CS
1190 }
1191
064d4355 1192 if (is_debug)
5e81f5dd
DS
1193 zlog_debug(
1194 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1195 __func__, buf, (void *)old_route,
1196 old_route->path.cost, route->path.cost,
b9b87bfc 1197 listcount(old_route->nh_list));
064d4355 1198
6f19bb0e
CS
1199 /* For Inter-Prefix route: Update RIB/FIB,
1200 * For Inter-Router trigger summary update
1201 */
d62a17ae 1202 if (table->hook_add)
e285b70d 1203 (*table->hook_add)(old_route);
d62a17ae 1204
1205 /* Delete new route */
1206 ospf6_route_delete(route);
99ab28cb
CS
1207 break;
1208 }
1209
b9b87bfc
S
1210 /* If the old entry is not updated and old entry not found or old entry
1211 * does not match with the new entry then add the new route
1212 */
99ab28cb 1213 if (old_entry_updated == false) {
b9b87bfc
S
1214 if ((old == NULL) || (old->type != route->type)
1215 || (old->path.type != route->path.type))
1216 add_route = true;
1217 }
1218
1219 if (add_route) {
6f19bb0e 1220 if (is_debug) {
5e81f5dd 1221 zlog_debug(
b9b87bfc 1222 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
5e81f5dd 1223 __func__, buf, route->path.cost,
dc138868
DL
1224 listcount(route->nh_list),
1225 &route->path.origin.adv_router);
6f19bb0e
CS
1226 }
1227
1228 path = ospf6_path_dup(&route->path);
1229 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
1230 listnode_add_sort(route->paths, path);
d62a17ae 1231 /* ospf6_ia_add_nw_route (table, &prefix, route); */
e285b70d 1232 ospf6_route_add(route, table);
c3c0ac83 1233 }
049207c3 1234}
1235
beadc736 1236void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
1237 struct ospf6 *ospf6)
ccb59b11 1238{
d62a17ae 1239 struct ospf6_lsa *lsa;
1240 struct ospf6_area *oa;
d7c0a89a 1241 uint16_t type;
d62a17ae 1242
beadc736 1243 oa = ospf6_area_lookup(route->path.area_id, ospf6);
d62a17ae 1244 /*
1245 * It is possible to designate a non backbone
1246 * area first. If that is the case safely
1247 * fall out of this function.
1248 */
1249 if (oa == NULL)
1250 return;
1251
1252 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1253 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1254 ospf6_abr_examin_summary(lsa, oa);
1255
1256 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1257 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1258 ospf6_abr_examin_summary(lsa, oa);
ccb59b11 1259}
1260
d62a17ae 1261void ospf6_abr_reimport(struct ospf6_area *oa)
34956b31 1262{
d62a17ae 1263 struct ospf6_lsa *lsa;
d7c0a89a 1264 uint16_t type;
34956b31 1265
d62a17ae 1266 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1267 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1268 ospf6_abr_examin_summary(lsa, oa);
34956b31 1269
d62a17ae 1270 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1271 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1272 ospf6_abr_examin_summary(lsa, oa);
34956b31 1273}
1274
d62a17ae 1275void ospf6_abr_prefix_resummarize(struct ospf6 *o)
ca1f4309 1276{
d62a17ae 1277 struct ospf6_route *route;
ca1f4309 1278
d62a17ae 1279 if (IS_OSPF6_DEBUG_ABR)
1280 zlog_debug("Re-examining Inter-Prefix Summaries");
ca1f4309 1281
d62a17ae 1282 for (route = ospf6_route_head(o->route_table); route;
1283 route = ospf6_route_next(route))
beadc736 1284 ospf6_abr_originate_summary(route, o);
ca1f4309 1285
d62a17ae 1286 if (IS_OSPF6_DEBUG_ABR)
1287 zlog_debug("Finished re-examining Inter-Prefix Summaries");
ca1f4309 1288}
34956b31 1289
6b0655a2 1290
049207c3 1291/* Display functions */
d62a17ae 1292static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1293 char *buf, int buflen,
1294 int pos)
e68a6767 1295{
d62a17ae 1296 struct ospf6_inter_prefix_lsa *prefix_lsa;
1297 struct in6_addr in6;
7533cad7 1298 char tbuf[16];
d62a17ae 1299
1300 if (lsa != NULL) {
1301 prefix_lsa =
1302 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1303 lsa->header);
1304
b8ce0c36 1305 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
d62a17ae 1306 if (buf) {
1307 inet_ntop(AF_INET6, &in6, buf, buflen);
7533cad7
QY
1308 snprintf(tbuf, sizeof(tbuf), "/%d",
1309 prefix_lsa->prefix.prefix_length);
1310 strlcat(buf, tbuf, buflen);
d62a17ae 1311 }
e68a6767 1312 }
e68a6767 1313
d62a17ae 1314 return (buf);
e68a6767
DD
1315}
1316
d62a17ae 1317static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
e4bacbaa
YR
1318 struct ospf6_lsa *lsa,
1319 json_object *json_obj,
1320 bool use_json)
049207c3 1321{
d62a17ae 1322 struct ospf6_inter_prefix_lsa *prefix_lsa;
1323 char buf[INET6_ADDRSTRLEN];
049207c3 1324
d62a17ae 1325 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1326 lsa->header);
049207c3 1327
e4bacbaa
YR
1328 if (use_json) {
1329 json_object_int_add(
1330 json_obj, "metric",
1331 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1332 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1333 buf, sizeof(buf));
1334 json_object_string_add(json_obj, "prefixOptions", buf);
1335 json_object_string_add(
1336 json_obj, "prefix",
1337 ospf6_inter_area_prefix_lsa_get_prefix_str(
1338 lsa, buf, sizeof(buf), 0));
1339 } else {
1340 vty_out(vty, " Metric: %lu\n",
1341 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
049207c3 1342
e4bacbaa
YR
1343 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1344 buf, sizeof(buf));
1345 vty_out(vty, " Prefix Options: %s\n", buf);
049207c3 1346
e4bacbaa
YR
1347 vty_out(vty, " Prefix: %s\n",
1348 ospf6_inter_area_prefix_lsa_get_prefix_str(
1349 lsa, buf, sizeof(buf), 0));
1350 }
049207c3 1351
d62a17ae 1352 return 0;
049207c3 1353}
1354
d62a17ae 1355static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1356 char *buf, int buflen,
1357 int pos)
e68a6767 1358{
d62a17ae 1359 struct ospf6_inter_router_lsa *router_lsa;
e68a6767 1360
d62a17ae 1361 if (lsa != NULL) {
1362 router_lsa =
1363 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1364 lsa->header);
e68a6767
DD
1365
1366
d62a17ae 1367 if (buf)
1368 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1369 }
e68a6767 1370
d62a17ae 1371 return (buf);
e68a6767
DD
1372}
1373
d62a17ae 1374static int ospf6_inter_area_router_lsa_show(struct vty *vty,
e4bacbaa
YR
1375 struct ospf6_lsa *lsa,
1376 json_object *json_obj,
1377 bool use_json)
049207c3 1378{
d62a17ae 1379 struct ospf6_inter_router_lsa *router_lsa;
1380 char buf[64];
049207c3 1381
d62a17ae 1382 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1383 lsa->header);
049207c3 1384
d62a17ae 1385 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
e4bacbaa
YR
1386 if (use_json) {
1387 json_object_string_add(json_obj, "options", buf);
1388 json_object_int_add(
1389 json_obj, "metric",
1390 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1391 } else {
1392 vty_out(vty, " Options: %s\n", buf);
1393 vty_out(vty, " Metric: %lu\n",
1394 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1395 }
e68a6767 1396
d62a17ae 1397 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
e4bacbaa
YR
1398 if (use_json)
1399 json_object_string_add(json_obj, "destinationRouterId", buf);
1400 else
1401 vty_out(vty, " Destination Router ID: %s\n", buf);
049207c3 1402
d62a17ae 1403 return 0;
049207c3 1404}
1405
1406/* Debug commands */
1407DEFUN (debug_ospf6_abr,
1408 debug_ospf6_abr_cmd,
1409 "debug ospf6 abr",
1410 DEBUG_STR
1411 OSPF6_STR
1412 "Debug OSPFv3 ABR function\n"
1413 )
1414{
d62a17ae 1415 OSPF6_DEBUG_ABR_ON();
1416 return CMD_SUCCESS;
049207c3 1417}
1418
1419DEFUN (no_debug_ospf6_abr,
1420 no_debug_ospf6_abr_cmd,
1421 "no debug ospf6 abr",
1422 NO_STR
1423 DEBUG_STR
1424 OSPF6_STR
1425 "Debug OSPFv3 ABR function\n"
1426 )
1427{
d62a17ae 1428 OSPF6_DEBUG_ABR_OFF();
1429 return CMD_SUCCESS;
049207c3 1430}
1431
d62a17ae 1432int config_write_ospf6_debug_abr(struct vty *vty)
049207c3 1433{
d62a17ae 1434 if (IS_OSPF6_DEBUG_ABR)
1435 vty_out(vty, "debug ospf6 abr\n");
1436 return 0;
049207c3 1437}
1438
d62a17ae 1439void install_element_ospf6_debug_abr(void)
049207c3 1440{
d62a17ae 1441 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1442 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1443 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1444 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
049207c3 1445}
1446
4062abfa 1447static struct ospf6_lsa_handler inter_prefix_handler = {
3981b5c7
VJ
1448 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1449 .lh_name = "Inter-Prefix",
1450 .lh_short_name = "IAP",
1451 .lh_show = ospf6_inter_area_prefix_lsa_show,
1452 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
996c9314 1453 .lh_debug = 0};
6452df09 1454
4062abfa 1455static struct ospf6_lsa_handler inter_router_handler = {
3981b5c7
VJ
1456 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1457 .lh_name = "Inter-Router",
1458 .lh_short_name = "IAR",
1459 .lh_show = ospf6_inter_area_router_lsa_show,
1460 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
996c9314 1461 .lh_debug = 0};
6452df09 1462
d62a17ae 1463void ospf6_abr_init(void)
049207c3 1464{
d62a17ae 1465 ospf6_install_lsa_handler(&inter_prefix_handler);
1466 ospf6_install_lsa_handler(&inter_router_handler);
049207c3 1467}