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