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