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