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