]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
*: spelchek
[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
243 if (is_debug) {
d62a17ae 244 prefix2str(&route->prefix, buf, sizeof(buf));
6f19bb0e
CS
245 zlog_debug("Originating summary in area %s for %s cost %u",
246 area->name, buf, route->path.cost);
d62a17ae 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) {
0437e105 324 /* Only the preferred best path is considered */
d62a17ae 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 */
427f8e61
DL
412 if (PREFIX_LIST_OUT(area))
413 if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
414 != PREFIX_PERMIT) {
415 if (is_debug) {
996c9314
LB
416 inet_ntop(
417 AF_INET,
418 &(ADV_ROUTER_IN_PREFIX(&route->prefix)),
419 buf, sizeof(buf));
427f8e61
DL
420 zlog_debug(
421 "prefix %s was denied by filter-list out",
422 buf);
d62a17ae 423 }
427f8e61
DL
424 return 0;
425 }
d62a17ae 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);
c3c0ac83 449 }
d62a17ae 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);
c3c0ac83 496 }
d62a17ae 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;
6452df09 518}
519
d62a17ae 520void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
ca1f4309 521{
d62a17ae 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);
ca1f4309
DS
530}
531
d7c0a89a
QY
532static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
533 struct ospf6 *o)
6452df09 534{
d62a17ae 535 struct ospf6_route *ro;
d7c0a89a 536 uint32_t cost = 0;
d62a17ae 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;
ca1f4309
DS
547}
548
549static inline int
d7c0a89a 550ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
ca1f4309 551{
d62a17ae 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;
c3c0ac83 579 }
d62a17ae 580
581 return (redo_summary);
ca1f4309
DS
582}
583
d62a17ae 584static void ospf6_abr_range_update(struct ospf6_route *range)
ca1f4309 585{
d7c0a89a 586 uint32_t cost = 0;
d62a17ae 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 }
c3c0ac83 636 }
049207c3 637}
638
d62a17ae 639void ospf6_abr_originate_summary(struct ospf6_route *route)
049207c3 640{
d62a17ae 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);
48725111 647 if (!oa) {
648 zlog_err("OSPFv6 area lookup failed");
649 return;
650 }
651
d62a17ae 652 range = ospf6_route_lookup_bestmatch(&route->prefix,
653 oa->range_table);
654 if (range) {
655 ospf6_abr_range_update(range);
656 }
c3c0ac83 657 }
6452df09 658
d62a17ae 659 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
660 ospf6_abr_originate_summary_to_area(route, oa);
049207c3 661}
662
d62a17ae 663void ospf6_abr_defaults_to_stub(struct ospf6 *o)
ca1f4309 664{
d62a17ae 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 }
ca1f4309 706 }
d62a17ae 707 ospf6_route_delete(def);
ca1f4309
DS
708}
709
6f19bb0e
CS
710void 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
774void 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
049207c3 840/* RFC 2328 16.2. Calculating the inter-area routes */
d62a17ae 841void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
049207c3 842{
d62a17ae 843 struct prefix prefix, abr_prefix;
844 struct ospf6_route_table *table = NULL;
99ab28cb 845 struct ospf6_route *range, *route, *old = NULL, *old_route;
d62a17ae 846 struct ospf6_route *abr_entry;
d7c0a89a 847 uint8_t type = 0;
d62a17ae 848 char options[3] = {0, 0, 0};
d7c0a89a
QY
849 uint8_t prefix_options = 0;
850 uint32_t cost = 0;
851 uint8_t router_bits = 0;
d62a17ae 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;
99ab28cb 856 bool old_entry_updated = false;
6f19bb0e
CS
857 struct ospf6_path *path, *o_path, *ecmp_path;
858 struct listnode *anode;
859 char adv_router[16];
d62a17ae 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++;
99ab28cb
CS
866 zlog_debug("%s: Examin %s in area %s",
867 __PRETTY_FUNCTION__, lsa->name, oa->name);
d62a17ae 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;
b8ce0c36 875 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
876 &prefix_lsa->prefix);
d62a17ae 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++;
99ab28cb
CS
886 zlog_debug("%s: Examin %s in area %s",
887 __PRETTY_FUNCTION__, lsa->name, oa->name);
d62a17ae 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
6f19bb0e
CS
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) {
6f19bb0e
CS
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 }
d62a17ae 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)
6f19bb0e 956 ospf6_abr_old_route_remove(lsa, old, table);
d62a17ae 957 return;
958 }
959 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
960 if (is_debug)
a2d0055a
CS
961 zlog_debug("%s: LSA %s is MaxAge, ignore",
962 __PRETTY_FUNCTION__, lsa->name);
d62a17ae 963 if (old)
6f19bb0e 964 ospf6_abr_old_route_remove(lsa, old, table);
d62a17ae 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)
6f19bb0e
CS
971 zlog_debug("LSA %s is self-originated, ignore",
972 lsa->name);
d62a17ae 973 if (old)
974 ospf6_route_remove(old, table);
975 return;
01879114 976 }
d62a17ae 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)) {
8934b81c
QY
981 /* must have been set in previous block */
982 assert(prefix_lsa);
983
d62a17ae 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 }
01879114 1004 }
d62a17ae 1005
1006 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1007 /* To pass test suites */
554bfe88 1008 assert(router_lsa);
d62a17ae 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)
a2d0055a
CS
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 }
d62a17ae 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 */
6f19bb0e 1081 if (PREFIX_LIST_IN(oa)) {
427f8e61
DL
1082 if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
1083 != PREFIX_PERMIT) {
1084 if (is_debug)
996c9314 1085 zlog_debug("Prefix was denied by prefix-list");
427f8e61
DL
1086 if (old)
1087 ospf6_route_remove(old, table);
1088 return;
1089 }
6f19bb0e 1090 }
d62a17ae 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). */
6f19bb0e 1095 route = ospf6_route_create();
d62a17ae 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
6f19bb0e
CS
1111 /* copy brouter rechable nexthops into the route. */
1112 ospf6_route_copy_nexthops(route, abr_entry);
064d4355 1113
d62a17ae 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
99ab28cb
CS
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;
064d4355 1126
99ab28cb
CS
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 }
6f19bb0e
CS
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);
99ab28cb
CS
1144 continue;
1145 }
1146
6f19bb0e 1147 ospf6_route_merge_nexthops(old_route, route);
99ab28cb 1148 old_entry_updated = true;
6f19bb0e
CS
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
064d4355 1188 if (is_debug)
6f19bb0e
CS
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,
996c9314 1192 listcount(route->nh_list));
064d4355 1193
6f19bb0e
CS
1194 /* For Inter-Prefix route: Update RIB/FIB,
1195 * For Inter-Router trigger summary update
1196 */
d62a17ae 1197 if (table->hook_add)
6f19bb0e 1198 (*table->hook_add)(old_route);
d62a17ae 1199
1200 /* Delete new route */
1201 ospf6_route_delete(route);
99ab28cb
CS
1202 break;
1203 }
1204
1205 if (old_entry_updated == false) {
6f19bb0e
CS
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 ",
c601fa3f 1210 __PRETTY_FUNCTION__, buf, route->path.cost,
6f19bb0e
CS
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
d62a17ae 1218 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1219 ospf6_route_add(route, table);
c3c0ac83 1220 }
049207c3 1221}
1222
d7c0a89a 1223void ospf6_abr_examin_brouter(uint32_t router_id)
ccb59b11 1224{
d62a17ae 1225 struct ospf6_lsa *lsa;
1226 struct ospf6_area *oa;
d7c0a89a 1227 uint16_t type;
d62a17ae 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);
ccb59b11 1249}
1250
d62a17ae 1251void ospf6_abr_reimport(struct ospf6_area *oa)
34956b31 1252{
d62a17ae 1253 struct ospf6_lsa *lsa;
d7c0a89a 1254 uint16_t type;
34956b31 1255
d62a17ae 1256 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1257 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1258 ospf6_abr_examin_summary(lsa, oa);
34956b31 1259
d62a17ae 1260 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1261 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1262 ospf6_abr_examin_summary(lsa, oa);
34956b31 1263}
1264
d62a17ae 1265void ospf6_abr_prefix_resummarize(struct ospf6 *o)
ca1f4309 1266{
d62a17ae 1267 struct ospf6_route *route;
ca1f4309 1268
d62a17ae 1269 if (IS_OSPF6_DEBUG_ABR)
1270 zlog_debug("Re-examining Inter-Prefix Summaries");
ca1f4309 1271
d62a17ae 1272 for (route = ospf6_route_head(o->route_table); route;
1273 route = ospf6_route_next(route))
1274 ospf6_abr_originate_summary(route);
ca1f4309 1275
d62a17ae 1276 if (IS_OSPF6_DEBUG_ABR)
1277 zlog_debug("Finished re-examining Inter-Prefix Summaries");
ca1f4309 1278}
34956b31 1279
6b0655a2 1280
049207c3 1281/* Display functions */
d62a17ae 1282static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1283 char *buf, int buflen,
1284 int pos)
e68a6767 1285{
d62a17ae 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
b8ce0c36 1294 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
d62a17ae 1295 if (buf) {
1296 inet_ntop(AF_INET6, &in6, buf, buflen);
1297 sprintf(&buf[strlen(buf)], "/%d",
1298 prefix_lsa->prefix.prefix_length);
1299 }
e68a6767 1300 }
e68a6767 1301
d62a17ae 1302 return (buf);
e68a6767
DD
1303}
1304
d62a17ae 1305static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1306 struct ospf6_lsa *lsa)
049207c3 1307{
d62a17ae 1308 struct ospf6_inter_prefix_lsa *prefix_lsa;
1309 char buf[INET6_ADDRSTRLEN];
049207c3 1310
d62a17ae 1311 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1312 lsa->header);
049207c3 1313
d62a17ae 1314 vty_out(vty, " Metric: %lu\n",
d7c0a89a 1315 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
049207c3 1316
d62a17ae 1317 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf,
1318 sizeof(buf));
1319 vty_out(vty, " Prefix Options: %s\n", buf);
049207c3 1320
d62a17ae 1321 vty_out(vty, " Prefix: %s\n",
1322 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf,
1323 sizeof(buf), 0));
049207c3 1324
d62a17ae 1325 return 0;
049207c3 1326}
1327
d62a17ae 1328static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1329 char *buf, int buflen,
1330 int pos)
e68a6767 1331{
d62a17ae 1332 struct ospf6_inter_router_lsa *router_lsa;
e68a6767 1333
d62a17ae 1334 if (lsa != NULL) {
1335 router_lsa =
1336 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1337 lsa->header);
e68a6767
DD
1338
1339
d62a17ae 1340 if (buf)
1341 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1342 }
e68a6767 1343
d62a17ae 1344 return (buf);
e68a6767
DD
1345}
1346
d62a17ae 1347static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1348 struct ospf6_lsa *lsa)
049207c3 1349{
d62a17ae 1350 struct ospf6_inter_router_lsa *router_lsa;
1351 char buf[64];
049207c3 1352
d62a17ae 1353 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1354 lsa->header);
049207c3 1355
d62a17ae 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",
d7c0a89a 1359 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
e68a6767 1360
d62a17ae 1361 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1362 vty_out(vty, " Destination Router ID: %s\n", buf);
049207c3 1363
d62a17ae 1364 return 0;
049207c3 1365}
1366
1367/* Debug commands */
1368DEFUN (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{
d62a17ae 1376 OSPF6_DEBUG_ABR_ON();
1377 return CMD_SUCCESS;
049207c3 1378}
1379
1380DEFUN (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{
d62a17ae 1389 OSPF6_DEBUG_ABR_OFF();
1390 return CMD_SUCCESS;
049207c3 1391}
1392
d62a17ae 1393int config_write_ospf6_debug_abr(struct vty *vty)
049207c3 1394{
d62a17ae 1395 if (IS_OSPF6_DEBUG_ABR)
1396 vty_out(vty, "debug ospf6 abr\n");
1397 return 0;
049207c3 1398}
1399
d62a17ae 1400void install_element_ospf6_debug_abr(void)
049207c3 1401{
d62a17ae 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);
049207c3 1406}
1407
d62a17ae 1408struct ospf6_lsa_handler inter_prefix_handler = {
3981b5c7
VJ
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,
996c9314 1414 .lh_debug = 0};
6452df09 1415
d62a17ae 1416struct ospf6_lsa_handler inter_router_handler = {
3981b5c7
VJ
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,
996c9314 1422 .lh_debug = 0};
6452df09 1423
d62a17ae 1424void ospf6_abr_init(void)
049207c3 1425{
d62a17ae 1426 ospf6_install_lsa_handler(&inter_prefix_handler);
1427 ospf6_install_lsa_handler(&inter_router_handler);
049207c3 1428}