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