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