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