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