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