]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
Merge remote-tracking branch 'origin/master' into pim_lib_work2
[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 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "log.h"
26#include "prefix.h"
27#include "table.h"
28#include "vty.h"
29#include "linklist.h"
30#include "command.h"
3b68735f 31#include "thread.h"
34956b31 32#include "plist.h"
33#include "filter.h"
049207c3 34
35#include "ospf6_proto.h"
36#include "ospf6_route.h"
37#include "ospf6_lsa.h"
38#include "ospf6_route.h"
39#include "ospf6_lsdb.h"
6452df09 40#include "ospf6_message.h"
c3c0ac83 41#include "ospf6_zebra.h"
6452df09 42
049207c3 43#include "ospf6_top.h"
44#include "ospf6_area.h"
45#include "ospf6_interface.h"
6452df09 46#include "ospf6_neighbor.h"
47
6452df09 48#include "ospf6_flood.h"
3b68735f 49#include "ospf6_intra.h"
50#include "ospf6_abr.h"
049207c3 51#include "ospf6d.h"
52
53unsigned char conf_debug_ospf6_abr;
54
6452df09 55int
56ospf6_is_router_abr (struct ospf6 *o)
57{
52dc7ee6 58 struct listnode *node;
6452df09 59 struct ospf6_area *oa;
60 int area_count = 0;
61
1eb8ef25 62 for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa))
63 if (IS_AREA_ENABLED (oa))
64 area_count++;
6452df09 65
66 if (area_count > 1)
67 return 1;
68 return 0;
69}
70
c3c0ac83
DS
71static int
72ospf6_abr_nexthops_belong_to_area (struct ospf6_route *route,
73 struct ospf6_area *area)
74{
75 struct ospf6_interface *oi;
76
77 oi = ospf6_interface_lookup_by_ifindex (ospf6_route_get_first_nh_index(route));
78 if (oi && oi->area && oi->area == area)
79 return 1;
80 else
81 return 0;
82}
83
84static void
85ospf6_abr_delete_route (struct ospf6_route *range, struct ospf6_route *summary,
86 struct ospf6_route_table *summary_table,
87 struct ospf6_lsa *old)
88{
89 if (summary)
90 {
91 ospf6_route_remove (summary, summary_table);
92 }
93
ca1f4309 94 if (old && !OSPF6_LSA_IS_MAXAGE (old))
c3c0ac83
DS
95 ospf6_lsa_purge (old);
96}
97
3b68735f 98void
99ospf6_abr_enable_area (struct ospf6_area *area)
100{
101 struct ospf6_area *oa;
1eb8ef25 102 struct listnode *node, *nnode;
3b68735f 103
1eb8ef25 104 for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
ca1f4309
DS
105 /* update B bit for each area */
106 OSPF6_ROUTER_LSA_SCHEDULE (oa);
3b68735f 107}
108
109void
110ospf6_abr_disable_area (struct ospf6_area *area)
111{
112 struct ospf6_area *oa;
0f23bb67 113 struct ospf6_route *ro, *nro;
3b68735f 114 struct ospf6_lsa *old;
1eb8ef25 115 struct listnode *node, *nnode;
3b68735f 116
117 /* Withdraw all summary prefixes previously originated */
0f23bb67 118 for (ro = ospf6_route_head (area->summary_prefix); ro; ro = nro)
3b68735f 119 {
0f23bb67 120 nro = ospf6_route_next (ro);
3b68735f 121 old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
122 area->ospf6->router_id, area->lsdb);
123 if (old)
124 ospf6_lsa_purge (old);
125 ospf6_route_remove (ro, area->summary_prefix);
126 }
127
128 /* Withdraw all summary router-routes previously originated */
0f23bb67 129 for (ro = ospf6_route_head (area->summary_router); ro; ro = nro)
3b68735f 130 {
0f23bb67 131 nro = ospf6_route_next (ro);
3b68735f 132 old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
133 area->ospf6->router_id, area->lsdb);
134 if (old)
135 ospf6_lsa_purge (old);
136 ospf6_route_remove (ro, area->summary_router);
137 }
138
139 /* Schedule Router-LSA for each area (ABR status may change) */
1eb8ef25 140 for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
141 /* update B bit for each area */
142 OSPF6_ROUTER_LSA_SCHEDULE (oa);
3b68735f 143}
144
049207c3 145/* RFC 2328 12.4.3. Summary-LSAs */
ca1f4309
DS
146/* Returns 1 if a summary LSA has been generated for the area */
147/* This is used by the area/range logic to add/remove blackhole routes */
c3c0ac83 148int
6452df09 149ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
150 struct ospf6_area *area)
049207c3 151{
152 struct ospf6_lsa *lsa, *old = NULL;
049207c3 153 struct ospf6_route *summary, *range = NULL;
154 struct ospf6_area *route_area;
155 char buffer[OSPF6_MAX_LSASIZE];
156 struct ospf6_lsa_header *lsa_header;
157 caddr_t p;
158 struct ospf6_inter_prefix_lsa *prefix_lsa;
6452df09 159 struct ospf6_inter_router_lsa *router_lsa;
160 struct ospf6_route_table *summary_table = NULL;
161 u_int16_t type;
4690c7d7 162 char buf[PREFIX2STR_BUFFER];
1e05838a 163 int is_debug = 0;
6452df09 164
c3c0ac83
DS
165 /* Only destination type network, range or ASBR are considered */
166 if (route->type != OSPF6_DEST_TYPE_NETWORK &&
167 route->type != OSPF6_DEST_TYPE_RANGE &&
168 ((route->type != OSPF6_DEST_TYPE_ROUTER) ||
169 !CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
170 {
171 if (is_debug)
172 zlog_debug ("Route type is none of network, range nor ASBR, ignore");
173 return 0;
174 }
175
176 /* AS External routes are never considered */
177 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
178 route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
179 {
180 if (is_debug)
181 zlog_debug ("Path type is external, skip");
182 return 0;
183 }
184
185 /* do not generate if the path's area is the same as target area */
186 if (route->path.area_id == area->area_id)
187 {
188 if (is_debug)
189 zlog_debug ("The route is in the area itself, ignore");
190 return 0;
191 }
192
193 /* do not generate if the nexthops belongs to the target area */
194 if (ospf6_abr_nexthops_belong_to_area (route, area))
195 {
196 if (is_debug)
197 zlog_debug ("The route's nexthop is in the same area, ignore");
198 return 0;
199 }
200
201 if (route->type == OSPF6_DEST_TYPE_ROUTER)
202 {
203 if (ADV_ROUTER_IN_PREFIX (&route->prefix) == area->ospf6->router_id)
204 {
205 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf,
206 sizeof (buf));
207 zlog_debug ("%s: Skipping ASBR announcement for ABR (%s)", __func__,
208 buf);
209 return 0;
210 }
211 }
212
1e05838a 213 if (route->type == OSPF6_DEST_TYPE_ROUTER)
6452df09 214 {
1e05838a 215 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER))
6452df09 216 {
1e05838a 217 is_debug++;
3b68735f 218 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
6452df09 219 buf, sizeof (buf));
c6487d61 220 zlog_debug ("Originating summary in area %s for ASBR %s",
221 area->name, buf);
6452df09 222 }
1e05838a 223 summary_table = area->summary_router;
224 }
225 else
226 {
227 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX))
6452df09 228 {
1e05838a 229 is_debug++;
6452df09 230 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 231 zlog_debug ("Originating summary in area %s for %s",
232 area->name, buf);
6452df09 233 }
1e05838a 234 summary_table = area->summary_prefix;
6452df09 235 }
049207c3 236
6452df09 237 summary = ospf6_route_lookup (&route->prefix, summary_table);
049207c3 238 if (summary)
6452df09 239 old = ospf6_lsdb_lookup (summary->path.origin.type,
049207c3 240 summary->path.origin.id,
241 area->ospf6->router_id, area->lsdb);
242
243 /* if this route has just removed, remove corresponding LSA */
244 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
245 {
1e05838a 246 if (is_debug)
c6487d61 247 zlog_debug ("The route has just removed, purge previous LSA");
049207c3 248
c3c0ac83
DS
249 if (route->type == OSPF6_DEST_TYPE_RANGE)
250 {
251 /* Whether the route have active longer prefix */
252 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
253 {
254 if (is_debug)
255 zlog_debug ("The range is not active. withdraw");
256
257 ospf6_abr_delete_route (route, summary, summary_table, old);
258 }
259 }
260 else
261 if (old)
262 ospf6_lsa_purge (old);
049207c3 263
c3c0ac83 264 return 0;
049207c3 265 }
266
c3c0ac83 267 if ((route->type == OSPF6_DEST_TYPE_ROUTER) && IS_AREA_STUB(area))
049207c3 268 {
1e05838a 269 if (is_debug)
c3c0ac83 270 zlog_debug ("Area has been stubbed, purge Inter-Router LSA");
049207c3 271
c3c0ac83
DS
272 ospf6_abr_delete_route (route, summary, summary_table, old);
273 return 0;
049207c3 274 }
275
ca1f4309
DS
276 if (area->no_summary && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT))
277 {
278 if (is_debug)
279 zlog_debug ("Area has been stubbed, purge prefix LSA");
280
281 ospf6_abr_delete_route (route, summary, summary_table, old);
282 return 0;
283 }
284
6452df09 285 /* do not generate if the route cost is greater or equal to LSInfinity */
8551e6da 286 if (route->path.cost >= OSPF_LS_INFINITY)
049207c3 287 {
c3c0ac83
DS
288 /* When we're clearing the range route because all active prefixes
289 * under the range are gone, we set the range's cost to
290 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
291 * don't want to trigger the code here for that. This code is for
292 * handling routes that have gone to infinity. The range removal happens
293 * elsewhere.
294 */
295 if ((route->type != OSPF6_DEST_TYPE_RANGE) &&
296 (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC))
297 {
298 if (is_debug)
299 zlog_debug ("The cost exceeds LSInfinity, withdraw");
300 if (old)
301 ospf6_lsa_purge (old);
302 return 0;
303 }
049207c3 304 }
305
6452df09 306 /* if this is a route to ASBR */
307 if (route->type == OSPF6_DEST_TYPE_ROUTER)
049207c3 308 {
6452df09 309 /* Only the prefered best path is considered */
310 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
311 {
1e05838a 312 if (is_debug)
c6487d61 313 zlog_debug ("This is the secondary path to the ASBR, ignore");
c3c0ac83
DS
314 ospf6_abr_delete_route (route, summary, summary_table, old);
315 return 0;
6452df09 316 }
317
318 /* Do not generate if the area is stub */
319 /* XXX */
049207c3 320 }
321
6452df09 322 /* if this is an intra-area route, this may be suppressed by aggregation */
323 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
324 route->path.type == OSPF6_PATH_TYPE_INTRA)
049207c3 325 {
6452df09 326 /* search for configured address range for the route's area */
327 route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
328 assert (route_area);
329 range = ospf6_route_lookup_bestmatch (&route->prefix,
330 route_area->range_table);
331
332 /* ranges are ignored when originate backbone routes to transit area.
333 Otherwise, if ranges are configured, the route is suppressed. */
334 if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
8551e6da 335 (route->path.area_id != OSPF_AREA_BACKBONE ||
6452df09 336 ! IS_AREA_TRANSIT (area)))
337 {
1e05838a 338 if (is_debug)
6452df09 339 {
6452df09 340 prefix2str (&range->prefix, buf, sizeof (buf));
c6487d61 341 zlog_debug ("Suppressed by range %s of area %s",
6452df09 342 buf, route_area->name);
343 }
c3c0ac83
DS
344 ospf6_abr_delete_route (route, summary, summary_table, old);
345 return 0;
6452df09 346 }
347 }
348
349 /* If this is a configured address range */
350 if (route->type == OSPF6_DEST_TYPE_RANGE)
351 {
352 /* If DoNotAdvertise is set */
353 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
354 {
1e05838a 355 if (is_debug)
c6487d61 356 zlog_debug ("This is the range with DoNotAdvertise set. ignore");
c3c0ac83
DS
357 ospf6_abr_delete_route (route, summary, summary_table, old);
358 return 0;
6452df09 359 }
360
c3c0ac83 361 /* If there are no active prefixes in this range, remove */
6452df09 362 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
363 {
1e05838a 364 if (is_debug)
c6487d61 365 zlog_debug ("The range is not active. withdraw");
c3c0ac83
DS
366 ospf6_abr_delete_route (route, summary, summary_table, old);
367 return 0;
6452df09 368 }
049207c3 369 }
370
34956b31 371 /* Check export list */
372 if (EXPORT_NAME (area))
373 {
374 if (EXPORT_LIST (area) == NULL)
375 EXPORT_LIST (area) =
376 access_list_lookup (AFI_IP6, EXPORT_NAME (area));
377
378 if (EXPORT_LIST (area))
379 if (access_list_apply (EXPORT_LIST (area),
380 &route->prefix) == FILTER_DENY)
381 {
382 if (is_debug)
383 {
384 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
385 buf, sizeof(buf));
386 zlog_debug ("prefix %s was denied by export list", buf);
387 }
c3c0ac83 388 return 0;
34956b31 389 }
390 }
391
392 /* Check filter-list */
393 if (PREFIX_NAME_OUT (area))
394 {
395 if (PREFIX_LIST_OUT (area) == NULL)
396 PREFIX_LIST_OUT (area) =
397 prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area));
398
399 if (PREFIX_LIST_OUT (area))
400 if (prefix_list_apply (PREFIX_LIST_OUT (area),
401 &route->prefix) != PREFIX_PERMIT)
402 {
403 if (is_debug)
404 {
405 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
406 buf, sizeof (buf));
407 zlog_debug ("prefix %s was denied by filter-list out", buf);
408 }
c3c0ac83 409 return 0;
34956b31 410 }
411 }
412
049207c3 413 /* the route is going to be originated. store it in area's summary_table */
414 if (summary == NULL)
415 {
416 summary = ospf6_route_copy (route);
049207c3 417 summary->path.origin.adv_router = area->ospf6->router_id;
c3c0ac83
DS
418
419 if (route->type == OSPF6_DEST_TYPE_ROUTER)
420 {
421 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
422 summary->path.origin.id = ADV_ROUTER_IN_PREFIX (&route->prefix);
423 }
424 else
425 {
426 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
54c8d91e
DS
427 summary->path.origin.id =
428 ospf6_new_ls_id (summary->path.origin.type,
429 summary->path.origin.adv_router, area->lsdb);
c3c0ac83 430 }
9428f2dc 431 summary = ospf6_route_add (summary, summary_table);
6452df09 432 }
433 else
434 {
435 summary->type = route->type;
86f72dcb 436 quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed);
049207c3 437 }
438
6452df09 439 summary->path.router_bits = route->path.router_bits;
440 summary->path.options[0] = route->path.options[0];
441 summary->path.options[1] = route->path.options[1];
442 summary->path.options[2] = route->path.options[2];
443 summary->path.prefix_options = route->path.prefix_options;
444 summary->path.area_id = area->area_id;
445 summary->path.type = OSPF6_PATH_TYPE_INTER;
ca1f4309 446 summary->path.subtype = route->path.subtype;
6452df09 447 summary->path.cost = route->path.cost;
c3c0ac83 448 /* summary->nexthop[0] = route->nexthop[0]; */
6452df09 449
049207c3 450 /* prepare buffer */
451 memset (buffer, 0, sizeof (buffer));
452 lsa_header = (struct ospf6_lsa_header *) buffer;
049207c3 453
6452df09 454 if (route->type == OSPF6_DEST_TYPE_ROUTER)
455 {
456 router_lsa = (struct ospf6_inter_router_lsa *)
457 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
458 p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
459
460 /* Fill Inter-Area-Router-LSA */
461 router_lsa->options[0] = route->path.options[0];
462 router_lsa->options[1] = route->path.options[1];
463 router_lsa->options[2] = route->path.options[2];
464 OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
3b68735f 465 router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
6452df09 466 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
467 }
468 else
469 {
470 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
471 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
472 p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
473
474 /* Fill Inter-Area-Prefix-LSA */
475 OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
476 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
477 prefix_lsa->prefix.prefix_options = route->path.prefix_options;
478
479 /* set Prefix */
480 memcpy (p, &route->prefix.u.prefix6,
481 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
482 ospf6_prefix_apply_mask (&prefix_lsa->prefix);
483 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
484 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
485 }
049207c3 486
487 /* Fill LSA Header */
488 lsa_header->age = 0;
6452df09 489 lsa_header->type = type;
049207c3 490 lsa_header->id = summary->path.origin.id;
491 lsa_header->adv_router = area->ospf6->router_id;
492 lsa_header->seqnum =
493 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
494 lsa_header->adv_router, area->lsdb);
495 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
496
497 /* LSA checksum */
498 ospf6_lsa_checksum (lsa_header);
499
500 /* create LSA */
501 lsa = ospf6_lsa_create (lsa_header);
6452df09 502
049207c3 503 /* Originate */
6452df09 504 ospf6_lsa_originate_area (lsa, area);
c3c0ac83
DS
505
506 return 1;
6452df09 507}
508
c3c0ac83 509void
ca1f4309
DS
510ospf6_abr_range_reset_cost (struct ospf6 *ospf6)
511{
512 struct listnode *node, *nnode;
513 struct ospf6_area *oa;
514 struct ospf6_route *range;
515
516 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
517 for (range = ospf6_route_head (oa->range_table); range;
518 range = ospf6_route_next (range))
519 OSPF6_ABR_RANGE_CLEAR_COST(range);
520}
521
522static inline u_int32_t
523ospf6_abr_range_compute_cost (struct ospf6_route *range, struct ospf6 *o)
6452df09 524{
6452df09 525 struct ospf6_route *ro;
ca1f4309 526 u_int32_t cost = 0;
6452df09 527
ca1f4309
DS
528 for (ro = ospf6_route_match_head (&range->prefix, o->route_table);
529 ro; ro = ospf6_route_match_next (&range->prefix, ro))
530 {
531 if (ro->path.area_id == range->path.area_id &&
532 (ro->path.type == OSPF6_PATH_TYPE_INTRA) &&
533 ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
534 cost = MAX (cost, ro->path.cost);
535 }
536
537 return cost;
538}
539
540static inline int
541ospf6_abr_range_summary_needs_update (struct ospf6_route *range,
542 u_int32_t cost)
543{
544 int redo_summary = 0;
6452df09 545
c3c0ac83 546 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE))
6452df09 547 {
c3c0ac83 548 UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
ca1f4309 549 redo_summary = 1;
6452df09 550 }
ca1f4309 551 else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
c3c0ac83
DS
552 {
553 if (range->path.cost != 0)
554 {
555 range->path.cost = 0;
ca1f4309 556 redo_summary = 1;
c3c0ac83
DS
557 }
558 }
ca1f4309 559 else if (cost)
c3c0ac83 560 {
ca1f4309
DS
561 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
562 range->path.cost != range->path.u.cost_config))
c3c0ac83 563 {
ca1f4309
DS
564 range->path.cost = range->path.u.cost_config;
565 SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
566 redo_summary = 1;
c3c0ac83 567 }
ca1f4309
DS
568 else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path) &&
569 range->path.cost != cost)
c3c0ac83 570 {
ca1f4309
DS
571 range->path.cost = cost;
572 SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
573 redo_summary = 1;
c3c0ac83 574 }
c3c0ac83 575 }
ca1f4309 576 else if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
c3c0ac83 577 {
ca1f4309 578 /* Cost is zero, meaning no active range */
c3c0ac83
DS
579 UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
580 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
ca1f4309 581 redo_summary = 1;
c3c0ac83
DS
582 }
583
ca1f4309
DS
584 return (redo_summary);
585}
586
587static void
588ospf6_abr_range_update (struct ospf6_route *range)
589{
590 u_int32_t cost = 0;
591 struct listnode *node, *nnode;
592 struct ospf6_area *oa;
593 int summary_orig = 0;
594
595 assert (range->type == OSPF6_DEST_TYPE_RANGE);
596
597 /* update range's cost and active flag */
598 cost = ospf6_abr_range_compute_cost (range, ospf6);
599
600 /* Non-zero cost is a proxy for active longer prefixes in this range.
601 * If there are active routes covered by this range AND either the configured
602 * cost has changed or the summarized cost has changed then redo summaries.
603 * Alternately, if there are no longer active prefixes and there are
604 * summary announcements, withdraw those announcements.
605 *
606 * The don't advertise code relies on the path.cost being set to UNSPEC to
607 * work the first time. Subsequent times the path.cost is not 0 anyway if there
608 * were active ranges.
609 */
610
611 if (ospf6_abr_range_summary_needs_update (range, cost))
c3c0ac83 612 {
ca1f4309
DS
613 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
614 summary_orig += ospf6_abr_originate_summary_to_area (range, oa);
c3c0ac83 615
ca1f4309 616 if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY) && summary_orig)
c3c0ac83 617 {
ca1f4309
DS
618 if (! CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED))
619 {
620 if (IS_OSPF6_DEBUG_ABR)
621 zlog_debug ("Add discard route");
c3c0ac83 622
ca1f4309
DS
623 ospf6_zebra_add_discard (range);
624 }
c3c0ac83
DS
625 }
626 else
627 {
ca1f4309
DS
628 /* Summary removed or no summary generated as no specifics exist */
629 if (CHECK_FLAG (range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED))
630 {
631 if (IS_OSPF6_DEBUG_ABR)
632 zlog_debug ("Delete discard route");
c3c0ac83 633
ca1f4309
DS
634 ospf6_zebra_delete_discard (range);
635 }
c3c0ac83 636 }
6452df09 637 }
049207c3 638}
639
640void
6452df09 641ospf6_abr_originate_summary (struct ospf6_route *route)
049207c3 642{
1eb8ef25 643 struct listnode *node, *nnode;
049207c3 644 struct ospf6_area *oa;
6452df09 645 struct ospf6_route *range = NULL;
049207c3 646
6452df09 647 if (route->type == OSPF6_DEST_TYPE_NETWORK)
648 {
649 oa = ospf6_area_lookup (route->path.area_id, ospf6);
650 range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
651 if (range)
c3c0ac83
DS
652 {
653 ospf6_abr_range_update (range);
654 }
6452df09 655 }
656
1eb8ef25 657 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
658 ospf6_abr_originate_summary_to_area (route, oa);
049207c3 659}
660
ca1f4309
DS
661void
662ospf6_abr_defaults_to_stub (struct ospf6 *o)
663{
664 struct listnode *node, *nnode;
665 struct ospf6_area *oa;
666 struct ospf6_route *def, *route;
667
668 if (!o->backbone)
669 return;
670
671 def = ospf6_route_create();
672 def->type = OSPF6_DEST_TYPE_NETWORK;
673 def->prefix.family = AF_INET6;
674 def->prefix.prefixlen = 0;
675 memset (&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
676 def->type = OSPF6_DEST_TYPE_NETWORK;
677 def->path.type = OSPF6_PATH_TYPE_INTER;
678 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
679 def->path.area_id = o->backbone->area_id;
680
681 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
682 {
683 if (!IS_AREA_STUB (oa))
684 {
685 /* withdraw defaults when an area switches from stub to non-stub */
686 route = ospf6_route_lookup (&def->prefix, oa->summary_prefix);
687 if (route && (route->path.subtype == def->path.subtype))
688 {
689 if (IS_OSPF6_DEBUG_ABR)
690 zlog_debug ("Withdrawing default route from non-stubby area %s",
691 oa->name);
692 SET_FLAG (def->flag, OSPF6_ROUTE_REMOVE);
693 ospf6_abr_originate_summary_to_area (def, oa);
694 }
695 }
696 else
697 {
698 /* announce defaults to stubby areas */
699 if (IS_OSPF6_DEBUG_ABR)
700 zlog_debug ("Announcing default route into stubby area %s",
701 oa->name);
702 UNSET_FLAG (def->flag, OSPF6_ROUTE_REMOVE);
703 ospf6_abr_originate_summary_to_area (def, oa);
704 }
705 }
706 ospf6_route_delete (def);
707}
708
049207c3 709/* RFC 2328 16.2. Calculating the inter-area routes */
710void
711ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
712{
713 struct prefix prefix, abr_prefix;
714 struct ospf6_route_table *table = NULL;
715 struct ospf6_route *range, *route, *old = NULL;
716 struct ospf6_route *abr_entry;
6452df09 717 u_char type = 0;
049207c3 718 char options[3] = {0, 0, 0};
719 u_int8_t prefix_options = 0;
720 u_int32_t cost = 0;
63069ad6 721 u_char router_bits = 0;
4690c7d7 722 char buf[PREFIX2STR_BUFFER];
1e05838a 723 int is_debug = 0;
01879114
DD
724 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
725 struct ospf6_inter_router_lsa *router_lsa = NULL;
3b68735f 726
cf1ce250
PJ
727 memset (&prefix, 0, sizeof (prefix));
728
049207c3 729 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
730 {
1e05838a 731 if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
732 {
733 is_debug++;
c6487d61 734 zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
1e05838a 735 }
736
049207c3 737 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
738 OSPF6_LSA_HEADER_END (lsa->header);
739 prefix.family = AF_INET6;
740 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
741 ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
d91f35bc
DO
742 if (is_debug)
743 prefix2str (&prefix, buf, sizeof (buf));
049207c3 744 table = oa->ospf6->route_table;
745 type = OSPF6_DEST_TYPE_NETWORK;
746 prefix_options = prefix_lsa->prefix.prefix_options;
747 cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
748 }
749 else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
750 {
1e05838a 751 if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
752 {
753 is_debug++;
c6487d61 754 zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
1e05838a 755 }
756
049207c3 757 router_lsa = (struct ospf6_inter_router_lsa *)
758 OSPF6_LSA_HEADER_END (lsa->header);
759 ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
d91f35bc
DO
760 if (is_debug)
761 inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
c3c0ac83 762
049207c3 763 table = oa->ospf6->brouter_table;
764 type = OSPF6_DEST_TYPE_ROUTER;
765 options[0] = router_lsa->options[0];
766 options[1] = router_lsa->options[1];
767 options[2] = router_lsa->options[2];
768 cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
63069ad6 769 SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
049207c3 770 }
771 else
772 assert (0);
773
ccb59b11 774 /* Find existing route */
775 route = ospf6_route_lookup (&prefix, table);
776 if (route)
777 ospf6_route_lock (route);
778 while (route && ospf6_route_is_prefix (&prefix, route))
049207c3 779 {
780 if (route->path.area_id == oa->area_id &&
781 route->path.origin.type == lsa->header->type &&
782 route->path.origin.id == lsa->header->id &&
cf1ce250
PJ
783 route->path.origin.adv_router == lsa->header->adv_router &&
784 ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED))
049207c3 785 old = route;
ccb59b11 786 route = ospf6_route_next (route);
049207c3 787 }
c3c0ac83
DS
788 if (route)
789 ospf6_route_unlock (route);
049207c3 790
791 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
8551e6da 792 if (cost == OSPF_LS_INFINITY)
049207c3 793 {
1e05838a 794 if (is_debug)
c6487d61 795 zlog_debug ("cost is LS_INFINITY, ignore");
3b68735f 796 if (old)
63069ad6 797 ospf6_route_remove (old, table);
3b68735f 798 return;
799 }
800 if (OSPF6_LSA_IS_MAXAGE (lsa))
801 {
1e05838a 802 if (is_debug)
c6487d61 803 zlog_debug ("LSA is MaxAge, ignore");
049207c3 804 if (old)
63069ad6 805 ospf6_route_remove (old, table);
049207c3 806 return;
807 }
808
809 /* (2) if the LSA is self-originated, ignore */
810 if (lsa->header->adv_router == oa->ospf6->router_id)
811 {
1e05838a 812 if (is_debug)
c6487d61 813 zlog_debug ("LSA is self-originated, ignore");
049207c3 814 if (old)
63069ad6 815 ospf6_route_remove (old, table);
049207c3 816 return;
817 }
818
819 /* (3) if the prefix is equal to an active configured address range */
01879114 820 /* or if the NU bit is set in the prefix */
6452df09 821 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
049207c3 822 {
6452df09 823 range = ospf6_route_lookup (&prefix, oa->range_table);
824 if (range)
825 {
1e05838a 826 if (is_debug)
c6487d61 827 zlog_debug ("Prefix is equal to address range, ignore");
6452df09 828 if (old)
63069ad6 829 ospf6_route_remove (old, table);
6452df09 830 return;
831 }
01879114
DD
832
833 if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
834 OSPF6_PREFIX_OPTION_NU) ||
835 CHECK_FLAG (prefix_lsa->prefix.prefix_options,
836 OSPF6_PREFIX_OPTION_LA))
837 {
838 if (is_debug)
839 zlog_debug ("Prefix has NU/LA bit set, ignore");
840 if (old)
841 ospf6_route_remove (old, table);
842 return;
843 }
844 }
845
846 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
847 {
848 /* To pass test suites */
849 if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
850 ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
851 {
852 if (is_debug)
853 zlog_debug ("Prefix has NU/LA bit set, ignore");
854 if (old)
855 ospf6_route_remove (old, table);
c3c0ac83 856
01879114
DD
857 return;
858 }
c3c0ac83
DS
859 /* Avoid infinite recursion if someone has maliciously announced an
860 Inter-Router LSA for an ABR
861 */
862 if (lsa->header->adv_router == router_lsa->router_id)
863 {
864 if (is_debug)
865 zlog_debug ("Ignorning Inter-Router LSA for an ABR (%s)",
866 buf);
867 if (old)
868 ospf6_route_remove (old, table);
869
870 return;
871 }
049207c3 872 }
873
874 /* (4) if the routing table entry for the ABR does not exist */
875 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
876 abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
6452df09 877 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
ccb59b11 878 CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
6452df09 879 ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
049207c3 880 {
1e05838a 881 if (is_debug)
c6487d61 882 zlog_debug ("ABR router entry does not exist, ignore");
049207c3 883 if (old)
63069ad6 884 ospf6_route_remove (old, table);
049207c3 885 return;
886 }
887
34956b31 888 /* Check import list */
889 if (IMPORT_NAME (oa))
890 {
891 if (IMPORT_LIST (oa) == NULL)
892 IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa));
893
894 if (IMPORT_LIST (oa))
895 if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY)
896 {
897 if (is_debug)
898 zlog_debug ("Prefix was denied by import-list");
899 if (old)
900 ospf6_route_remove (old, table);
901 return;
902 }
903 }
904
905 /* Check input prefix-list */
906 if (PREFIX_NAME_IN (oa))
907 {
908 if (PREFIX_LIST_IN (oa) == NULL)
909 PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa));
910
911 if (PREFIX_LIST_IN (oa))
912 if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT)
913 {
914 if (is_debug)
915 zlog_debug ("Prefix was denied by prefix-list");
916 if (old)
917 ospf6_route_remove (old, table);
918 return;
919 }
920 }
921
c3c0ac83 922 /* (5),(6): the path preference is handled by the sorting
049207c3 923 in the routing table. Always install the path by substituting
924 old route (if any). */
925 if (old)
ccb59b11 926 route = ospf6_route_copy (old);
049207c3 927 else
928 route = ospf6_route_create ();
929
930 route->type = type;
931 route->prefix = prefix;
932 route->path.origin.type = lsa->header->type;
933 route->path.origin.id = lsa->header->id;
934 route->path.origin.adv_router = lsa->header->adv_router;
63069ad6 935 route->path.router_bits = router_bits;
049207c3 936 route->path.options[0] = options[0];
937 route->path.options[1] = options[1];
938 route->path.options[2] = options[2];
939 route->path.prefix_options = prefix_options;
940 route->path.area_id = oa->area_id;
941 route->path.type = OSPF6_PATH_TYPE_INTER;
942 route->path.cost = abr_entry->path.cost + cost;
049207c3 943
c3c0ac83
DS
944 ospf6_route_copy_nexthops (route, abr_entry);
945
946 /* (7) If the routes are identical, copy the next hops over to existing
947 route. ospf6's route table implementation will otherwise string both
948 routes, but keep the older one as the best route since the routes
949 are identical.
950 */
951 old = ospf6_route_lookup (&prefix, table);
952
953 if (old && (ospf6_route_cmp (route, old) == 0))
954 {
955 ospf6_route_merge_nexthops (old, route);
956 /* Update RIB/FIB */
957 if (table->hook_add)
958 (*table->hook_add) (old);
959
960 /* Delete new route */
961 ospf6_route_delete (route);
962 }
963 else
964 {
965 if (is_debug)
966 zlog_debug ("Install route: %s", buf);
967 /* ospf6_ia_add_nw_route (table, &prefix, route); */
968 ospf6_route_add (route, table);
969 }
049207c3 970}
971
ccb59b11 972void
973ospf6_abr_examin_brouter (u_int32_t router_id)
974{
975 struct ospf6_lsa *lsa;
976 struct ospf6_area *oa;
ccb59b11 977 u_int16_t type;
978
c3c0ac83
DS
979 if (ospf6_is_router_abr (ospf6))
980 oa = ospf6->backbone;
981 else
982 oa = listgetdata(listhead(ospf6->area_list));
ccb59b11 983
a807d96e
DS
984 /*
985 * It is possible to designate a non backbone
986 * area first. If that is the case safely
987 * fall out of this function.
988 */
989 if (oa == NULL)
990 return;
991
c3c0ac83
DS
992 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
993 for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
994 lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
995 ospf6_abr_examin_summary (lsa, oa);
996
997 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
998 for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
999 lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
1000 ospf6_abr_examin_summary (lsa, oa);
ccb59b11 1001}
1002
34956b31 1003void
1004ospf6_abr_reimport (struct ospf6_area *oa)
1005{
1006 struct ospf6_lsa *lsa;
1007 u_int16_t type;
1008
1009 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
1010 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1011 lsa = ospf6_lsdb_type_next (type, lsa))
1012 ospf6_abr_examin_summary (lsa, oa);
1013
1014 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
1015 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1016 lsa = ospf6_lsdb_type_next (type, lsa))
1017 ospf6_abr_examin_summary (lsa, oa);
1018}
1019
ca1f4309
DS
1020void
1021ospf6_abr_prefix_resummarize (struct ospf6 *o)
1022{
1023 struct ospf6_route *route;
1024
1025 if (IS_OSPF6_DEBUG_ABR)
1026 zlog_debug ("Re-examining Inter-Prefix Summaries");
1027
1028 for (route = ospf6_route_head (o->route_table); route;
1029 route = ospf6_route_next (route))
1030 ospf6_abr_originate_summary(route);
1031
1032 if (IS_OSPF6_DEBUG_ABR)
1033 zlog_debug ("Finished re-examining Inter-Prefix Summaries");
1034}
34956b31 1035
6b0655a2 1036
049207c3 1037/* Display functions */
e68a6767
DD
1038static char *
1039ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1040 int buflen, int pos)
1041{
1042 struct ospf6_inter_prefix_lsa *prefix_lsa;
1043 struct in6_addr in6;
1044
1045 if (lsa != NULL)
1046 {
1047 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
1048 OSPF6_LSA_HEADER_END (lsa->header);
1049
1050 ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
1051 if (buf)
1052 {
1053 inet_ntop (AF_INET6, &in6, buf, buflen);
1054 sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length);
1055 }
1056 }
1057
1058 return (buf);
1059}
1060
6ac29a51 1061static int
049207c3 1062ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1063{
1064 struct ospf6_inter_prefix_lsa *prefix_lsa;
e68a6767 1065 char buf[INET6_ADDRSTRLEN];
049207c3 1066
1067 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
1068 OSPF6_LSA_HEADER_END (lsa->header);
1069
1070 vty_out (vty, " Metric: %lu%s",
1071 (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL);
1072
1073 ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options,
1074 buf, sizeof (buf));
1075 vty_out (vty, " Prefix Options: %s%s", buf, VNL);
1076
e68a6767
DD
1077 vty_out (vty, " Prefix: %s%s",
1078 ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf),
1079 0), VNL);
049207c3 1080
1081 return 0;
1082}
1083
e68a6767
DD
1084static char *
1085ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
1086 int buflen, int pos)
1087{
1088 struct ospf6_inter_router_lsa *router_lsa;
1089
1090 if (lsa != NULL)
1091 {
1092 router_lsa = (struct ospf6_inter_router_lsa *)
1093 OSPF6_LSA_HEADER_END (lsa->header);
1094
1095
1096 if (buf)
1097 inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen);
1098 }
1099
1100 return (buf);
1101}
1102
6ac29a51 1103static int
049207c3 1104ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
1105{
1106 struct ospf6_inter_router_lsa *router_lsa;
1107 char buf[64];
1108
1109 router_lsa = (struct ospf6_inter_router_lsa *)
1110 OSPF6_LSA_HEADER_END (lsa->header);
1111
1112 ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf));
1113 vty_out (vty, " Options: %s%s", buf, VNL);
1114 vty_out (vty, " Metric: %lu%s",
1115 (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
e68a6767 1116
049207c3 1117 inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
1118 vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
1119
1120 return 0;
1121}
1122
1123/* Debug commands */
1124DEFUN (debug_ospf6_abr,
1125 debug_ospf6_abr_cmd,
1126 "debug ospf6 abr",
1127 DEBUG_STR
1128 OSPF6_STR
1129 "Debug OSPFv3 ABR function\n"
1130 )
1131{
1132 OSPF6_DEBUG_ABR_ON ();
1133 return CMD_SUCCESS;
1134}
1135
1136DEFUN (no_debug_ospf6_abr,
1137 no_debug_ospf6_abr_cmd,
1138 "no debug ospf6 abr",
1139 NO_STR
1140 DEBUG_STR
1141 OSPF6_STR
1142 "Debug OSPFv3 ABR function\n"
1143 )
1144{
1145 OSPF6_DEBUG_ABR_OFF ();
1146 return CMD_SUCCESS;
1147}
1148
1149int
1150config_write_ospf6_debug_abr (struct vty *vty)
1151{
1152 if (IS_OSPF6_DEBUG_ABR)
1153 vty_out (vty, "debug ospf6 abr%s", VNL);
1154 return 0;
1155}
1156
1157void
6ac29a51 1158install_element_ospf6_debug_abr (void)
049207c3 1159{
1160 install_element (ENABLE_NODE, &debug_ospf6_abr_cmd);
1161 install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1162 install_element (CONFIG_NODE, &debug_ospf6_abr_cmd);
1163 install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1164}
1165
6452df09 1166struct ospf6_lsa_handler inter_prefix_handler =
1167{
1168 OSPF6_LSTYPE_INTER_PREFIX,
1169 "Inter-Prefix",
e68a6767
DD
1170 "IAP",
1171 ospf6_inter_area_prefix_lsa_show,
1172 ospf6_inter_area_prefix_lsa_get_prefix_str,
6452df09 1173};
1174
1175struct ospf6_lsa_handler inter_router_handler =
1176{
1177 OSPF6_LSTYPE_INTER_ROUTER,
1178 "Inter-Router",
e68a6767
DD
1179 "IAR",
1180 ospf6_inter_area_router_lsa_show,
1181 ospf6_inter_area_router_lsa_get_prefix_str,
6452df09 1182};
1183
049207c3 1184void
6ac29a51 1185ospf6_abr_init (void)
049207c3 1186{
6452df09 1187 ospf6_install_lsa_handler (&inter_prefix_handler);
1188 ospf6_install_lsa_handler (&inter_router_handler);
049207c3 1189}
1190
1191