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