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