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