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