]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
SVN revisions 916-920 from Zebra. ABR support is almost done.
[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"
31
32#include "ospf6_proto.h"
33#include "ospf6_route.h"
34#include "ospf6_lsa.h"
35#include "ospf6_route.h"
36#include "ospf6_lsdb.h"
6452df09 37#include "ospf6_message.h"
38
049207c3 39#include "ospf6_top.h"
40#include "ospf6_area.h"
41#include "ospf6_interface.h"
6452df09 42#include "ospf6_neighbor.h"
43
049207c3 44#include "ospf6_abr.h"
6452df09 45#include "ospf6_flood.h"
049207c3 46#include "ospf6d.h"
47
48unsigned char conf_debug_ospf6_abr;
49
6452df09 50int
51ospf6_is_router_abr (struct ospf6 *o)
52{
53 listnode node;
54 struct ospf6_area *oa;
55 int area_count = 0;
56
57 for (node = listhead (o->area_list); node; nextnode (node))
58 {
59 oa = OSPF6_AREA (getdata (node));
60 if (IS_AREA_ENABLED (oa))
61 area_count++;
62 }
63
64 if (area_count > 1)
65 return 1;
66 return 0;
67}
68
049207c3 69/* RFC 2328 12.4.3. Summary-LSAs */
70void
6452df09 71ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
72 struct ospf6_area *area)
049207c3 73{
74 struct ospf6_lsa *lsa, *old = NULL;
75 struct ospf6_interface *oi;
76 struct ospf6_route *summary, *range = NULL;
77 struct ospf6_area *route_area;
78 char buffer[OSPF6_MAX_LSASIZE];
79 struct ospf6_lsa_header *lsa_header;
80 caddr_t p;
81 struct ospf6_inter_prefix_lsa *prefix_lsa;
6452df09 82 struct ospf6_inter_router_lsa *router_lsa;
83 struct ospf6_route_table *summary_table = NULL;
84 u_int16_t type;
85
86 if (IS_OSPF6_DEBUG_ABR)
87 {
88 char buf[64];
89 if (route->type == OSPF6_DEST_TYPE_ROUTER)
90 {
91 inet_ntop (AF_INET,
92 &(ospf6_linkstate_prefix_adv_router (&route->prefix)),
93 buf, sizeof (buf));
94 zlog_info ("Originating summary in area %s for ASBR %s",
95 area->name, buf);
96 }
97 else
98 {
99 prefix2str (&route->prefix, buf, sizeof (buf));
100 zlog_info ("Originating summary in area %s for %s",
101 area->name, buf);
102 }
103 }
049207c3 104
6452df09 105 if (route->type == OSPF6_DEST_TYPE_ROUTER)
106 summary_table = area->summary_router;
107 else
108 summary_table = area->summary_prefix;
109 summary = ospf6_route_lookup (&route->prefix, summary_table);
049207c3 110 if (summary)
6452df09 111 old = ospf6_lsdb_lookup (summary->path.origin.type,
049207c3 112 summary->path.origin.id,
113 area->ospf6->router_id, area->lsdb);
114
115 /* if this route has just removed, remove corresponding LSA */
116 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
117 {
6452df09 118 if (IS_OSPF6_DEBUG_ABR)
119 zlog_info ("The route has just removed, purge previous LSA");
120 if (summary)
121 ospf6_route_remove (summary, summary_table);
049207c3 122 if (old)
6452df09 123 ospf6_lsa_purge (old);
049207c3 124 return;
125 }
126
6452df09 127 /* Only destination type network, range or ASBR are considered */
128 if (route->type != OSPF6_DEST_TYPE_NETWORK &&
129 route->type != OSPF6_DEST_TYPE_RANGE &&
130 (route->type != OSPF6_DEST_TYPE_ROUTER ||
131 ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
049207c3 132 {
6452df09 133 if (IS_OSPF6_DEBUG_ABR)
134 zlog_info ("Route type is none of network, range nor ASBR, withdraw");
135 if (summary)
136 ospf6_route_remove (summary, summary_table);
049207c3 137 if (old)
6452df09 138 ospf6_lsa_purge (old);
049207c3 139 return;
140 }
141
142 /* AS External routes are never considered */
143 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
144 route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
145 {
6452df09 146 if (IS_OSPF6_DEBUG_ABR)
147 zlog_info ("Path type is external, withdraw");
148 if (summary)
149 ospf6_route_remove (summary, summary_table);
049207c3 150 if (old)
6452df09 151 ospf6_lsa_purge (old);
049207c3 152 return;
153 }
154
6452df09 155 /* do not generate if the path's area is the same as target area */
156 if (route->path.area_id == area->area_id)
049207c3 157 {
6452df09 158 if (IS_OSPF6_DEBUG_ABR)
159 zlog_info ("The route is in the area itself, ignore");
160 if (summary)
161 ospf6_route_remove (summary, summary_table);
049207c3 162 if (old)
6452df09 163 ospf6_lsa_purge (old);
049207c3 164 return;
165 }
166
6452df09 167 /* do not generate if the nexthops belongs to the target area */
168 oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
169 if (oi && oi->area && oi->area == area)
049207c3 170 {
6452df09 171 if (IS_OSPF6_DEBUG_ABR)
172 zlog_info ("The route's nexthop is in the same area, ignore");
173 if (summary)
174 ospf6_route_remove (summary, summary_table);
175 if (old)
176 ospf6_lsa_purge (old);
177 return;
049207c3 178 }
179
6452df09 180 /* do not generate if the route cost is greater or equal to LSInfinity */
181 if (route->path.cost >= LS_INFINITY)
049207c3 182 {
6452df09 183 if (IS_OSPF6_DEBUG_ABR)
184 zlog_info ("The cost exceeds LSInfinity, withdraw");
185 if (summary)
186 ospf6_route_remove (summary, summary_table);
049207c3 187 if (old)
6452df09 188 ospf6_lsa_purge (old);
049207c3 189 return;
190 }
191
6452df09 192 /* if this is a route to ASBR */
193 if (route->type == OSPF6_DEST_TYPE_ROUTER)
049207c3 194 {
6452df09 195 /* Only the prefered best path is considered */
196 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
197 {
198 if (IS_OSPF6_DEBUG_ABR)
199 zlog_info ("This is the secondary path to the ASBR, ignore");
200 if (summary)
201 ospf6_route_remove (summary, summary_table);
202 if (old)
203 ospf6_lsa_purge (old);
204 return;
205 }
206
207 /* Do not generate if the area is stub */
208 /* XXX */
049207c3 209 }
210
6452df09 211 /* if this is an intra-area route, this may be suppressed by aggregation */
212 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
213 route->path.type == OSPF6_PATH_TYPE_INTRA)
049207c3 214 {
6452df09 215 /* search for configured address range for the route's area */
216 route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
217 assert (route_area);
218 range = ospf6_route_lookup_bestmatch (&route->prefix,
219 route_area->range_table);
220
221 /* ranges are ignored when originate backbone routes to transit area.
222 Otherwise, if ranges are configured, the route is suppressed. */
223 if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
224 (route->path.area_id != BACKBONE_AREA_ID ||
225 ! IS_AREA_TRANSIT (area)))
226 {
227 if (IS_OSPF6_DEBUG_ABR)
228 {
229 char buf[64];
230 prefix2str (&range->prefix, buf, sizeof (buf));
231 zlog_info ("Suppressed by range %s of area %s",
232 buf, route_area->name);
233 }
234
235 if (summary)
236 ospf6_route_remove (summary, summary_table);
237 if (old)
238 ospf6_lsa_purge (old);
239 return;
240 }
241 }
242
243 /* If this is a configured address range */
244 if (route->type == OSPF6_DEST_TYPE_RANGE)
245 {
246 /* If DoNotAdvertise is set */
247 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
248 {
249 if (IS_OSPF6_DEBUG_ABR)
250 zlog_info ("This is the range with DoNotAdvertise set. ignore");
251 if (summary)
252 ospf6_route_remove (summary, summary_table);
253 if (old)
254 ospf6_lsa_purge (old);
255 return;
256 }
257
258 /* Whether the route have active longer prefix */
259 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
260 {
261 if (IS_OSPF6_DEBUG_ABR)
262 zlog_info ("The range is not active. withdraw");
263 if (summary)
264 ospf6_route_remove (summary, summary_table);
265 if (old)
266 ospf6_lsa_purge (old);
267 return;
268 }
049207c3 269 }
270
271 /* the route is going to be originated. store it in area's summary_table */
272 if (summary == NULL)
273 {
274 summary = ospf6_route_copy (route);
6452df09 275 if (route->type == OSPF6_DEST_TYPE_NETWORK ||
276 route->type == OSPF6_DEST_TYPE_RANGE)
277 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
278 else
279 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
049207c3 280 summary->path.origin.adv_router = area->ospf6->router_id;
281 summary->path.origin.id =
282 ospf6_new_ls_id (summary->path.origin.type,
283 summary->path.origin.adv_router, area->lsdb);
6452df09 284 ospf6_route_add (summary, summary_table);
285 }
286 else
287 {
288 summary->type = route->type;
289 gettimeofday (&summary->changed, NULL);
049207c3 290 }
291
6452df09 292 summary->path.router_bits = route->path.router_bits;
293 summary->path.options[0] = route->path.options[0];
294 summary->path.options[1] = route->path.options[1];
295 summary->path.options[2] = route->path.options[2];
296 summary->path.prefix_options = route->path.prefix_options;
297 summary->path.area_id = area->area_id;
298 summary->path.type = OSPF6_PATH_TYPE_INTER;
299 summary->path.cost = route->path.cost;
300 summary->nexthop[0] = route->nexthop[0];
301
049207c3 302 /* prepare buffer */
303 memset (buffer, 0, sizeof (buffer));
304 lsa_header = (struct ospf6_lsa_header *) buffer;
049207c3 305
6452df09 306 if (route->type == OSPF6_DEST_TYPE_ROUTER)
307 {
308 router_lsa = (struct ospf6_inter_router_lsa *)
309 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
310 p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
311
312 /* Fill Inter-Area-Router-LSA */
313 router_lsa->options[0] = route->path.options[0];
314 router_lsa->options[1] = route->path.options[1];
315 router_lsa->options[2] = route->path.options[2];
316 OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
317 router_lsa->router_id =
318 ospf6_linkstate_prefix_adv_router (&route->prefix);
319 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
320 }
321 else
322 {
323 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
324 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
325 p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
326
327 /* Fill Inter-Area-Prefix-LSA */
328 OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
329 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
330 prefix_lsa->prefix.prefix_options = route->path.prefix_options;
331
332 /* set Prefix */
333 memcpy (p, &route->prefix.u.prefix6,
334 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
335 ospf6_prefix_apply_mask (&prefix_lsa->prefix);
336 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
337 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
338 }
049207c3 339
340 /* Fill LSA Header */
341 lsa_header->age = 0;
6452df09 342 lsa_header->type = type;
049207c3 343 lsa_header->id = summary->path.origin.id;
344 lsa_header->adv_router = area->ospf6->router_id;
345 lsa_header->seqnum =
346 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
347 lsa_header->adv_router, area->lsdb);
348 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
349
350 /* LSA checksum */
351 ospf6_lsa_checksum (lsa_header);
352
353 /* create LSA */
354 lsa = ospf6_lsa_create (lsa_header);
6452df09 355
356 if (IS_OSPF6_DEBUG_ABR)
357 zlog_info ("Originate as %s", lsa->name);
049207c3 358
359 /* Originate */
6452df09 360 ospf6_lsa_originate_area (lsa, area);
361}
362
363void
364ospf6_abr_range_update (struct ospf6_route *range)
365{
366 u_int32_t cost = 0;
367 struct ospf6_route *ro;
368
369 assert (range->type == OSPF6_DEST_TYPE_RANGE);
370
371 /* update range's cost and active flag */
372 for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
373 ro; ro = ospf6_route_match_next (&range->prefix, ro))
374 {
375 if (ro->path.area_id == range->path.area_id &&
376 ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
377 cost = MAX (cost, ro->path.cost);
378 }
379
380 if (range->path.cost != cost)
381 {
382 range->path.cost = cost;
383
384 if (range->path.cost)
385 SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
386 else
387 UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
388
389 ospf6_abr_originate_summary (range);
390 }
049207c3 391}
392
393void
6452df09 394ospf6_abr_originate_summary (struct ospf6_route *route)
049207c3 395{
396 listnode node;
397 struct ospf6_area *oa;
6452df09 398 struct ospf6_route *range = NULL;
049207c3 399
6452df09 400 if (route->type == OSPF6_DEST_TYPE_NETWORK)
401 {
402 oa = ospf6_area_lookup (route->path.area_id, ospf6);
403 range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
404 if (range)
405 ospf6_abr_range_update (range);
406 }
407
408 for (node = listhead (ospf6->area_list); node; nextnode (node))
049207c3 409 {
410 oa = (struct ospf6_area *) getdata (node);
6452df09 411 ospf6_abr_originate_summary_to_area (route, oa);
049207c3 412 }
413}
414
415/* RFC 2328 16.2. Calculating the inter-area routes */
416void
417ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
418{
419 struct prefix prefix, abr_prefix;
420 struct ospf6_route_table *table = NULL;
421 struct ospf6_route *range, *route, *old = NULL;
422 struct ospf6_route *abr_entry;
6452df09 423 u_char type = 0;
049207c3 424 char options[3] = {0, 0, 0};
425 u_int8_t prefix_options = 0;
426 u_int32_t cost = 0;
427 int i;
428
429 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
430 {
431 struct ospf6_inter_prefix_lsa *prefix_lsa;
432 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
433 OSPF6_LSA_HEADER_END (lsa->header);
434 prefix.family = AF_INET6;
435 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
436 ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
437 table = oa->ospf6->route_table;
438 type = OSPF6_DEST_TYPE_NETWORK;
439 prefix_options = prefix_lsa->prefix.prefix_options;
440 cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
441 }
442 else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
443 {
444 struct ospf6_inter_router_lsa *router_lsa;
445 router_lsa = (struct ospf6_inter_router_lsa *)
446 OSPF6_LSA_HEADER_END (lsa->header);
447 ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
448 table = oa->ospf6->brouter_table;
449 type = OSPF6_DEST_TYPE_ROUTER;
450 options[0] = router_lsa->options[0];
451 options[1] = router_lsa->options[1];
452 options[2] = router_lsa->options[2];
453 cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
454 }
455 else
456 assert (0);
457
458 for (route = ospf6_route_lookup (&prefix, table);
459 route && ospf6_route_is_prefix (&prefix, route);
460 route = ospf6_route_next (route))
461 {
462 if (route->path.area_id == oa->area_id &&
463 route->path.origin.type == lsa->header->type &&
464 route->path.origin.id == lsa->header->id &&
465 route->path.origin.adv_router == lsa->header->adv_router)
466 old = route;
467 }
468
469 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
470 if (cost == LS_INFINITY || OSPF6_LSA_IS_MAXAGE (lsa))
471 {
472 if (old)
473 ospf6_route_remove (old, oa->ospf6->route_table);
474 return;
475 }
476
477 /* (2) if the LSA is self-originated, ignore */
478 if (lsa->header->adv_router == oa->ospf6->router_id)
479 {
480 if (old)
481 ospf6_route_remove (old, oa->ospf6->route_table);
482 return;
483 }
484
485 /* (3) if the prefix is equal to an active configured address range */
6452df09 486 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
049207c3 487 {
6452df09 488 range = ospf6_route_lookup (&prefix, oa->range_table);
489 if (range)
490 {
491 if (old)
492 ospf6_route_remove (old, oa->ospf6->route_table);
493 return;
494 }
049207c3 495 }
496
497 /* (4) if the routing table entry for the ABR does not exist */
498 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
499 abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
6452df09 500 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
501 ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
049207c3 502 {
503 if (old)
504 ospf6_route_remove (old, oa->ospf6->route_table);
505 return;
506 }
507
508 /* (5),(6),(7) the path preference is handled by the sorting
509 in the routing table. Always install the path by substituting
510 old route (if any). */
511 if (old)
512 route = old;
513 else
514 route = ospf6_route_create ();
515
516 route->type = type;
517 route->prefix = prefix;
518 route->path.origin.type = lsa->header->type;
519 route->path.origin.id = lsa->header->id;
520 route->path.origin.adv_router = lsa->header->adv_router;
521 route->path.options[0] = options[0];
522 route->path.options[1] = options[1];
523 route->path.options[2] = options[2];
524 route->path.prefix_options = prefix_options;
525 route->path.area_id = oa->area_id;
526 route->path.type = OSPF6_PATH_TYPE_INTER;
527 route->path.cost = abr_entry->path.cost + cost;
528 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
529 route->nexthop[i] = abr_entry->nexthop[i];
530
531 ospf6_route_add (route, table);
532}
533
049207c3 534\f
535/* Display functions */
536int
537ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
538{
539 struct ospf6_inter_prefix_lsa *prefix_lsa;
540 struct in6_addr in6;
541 char buf[64];
542
543 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
544 OSPF6_LSA_HEADER_END (lsa->header);
545
546 vty_out (vty, " Metric: %lu%s",
547 (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL);
548
549 ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options,
550 buf, sizeof (buf));
551 vty_out (vty, " Prefix Options: %s%s", buf, VNL);
552
553 ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
554 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
555 vty_out (vty, " Prefix: %s/%d%s", buf,
556 prefix_lsa->prefix.prefix_length, VNL);
557
558 return 0;
559}
560
561int
562ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
563{
564 struct ospf6_inter_router_lsa *router_lsa;
565 char buf[64];
566
567 router_lsa = (struct ospf6_inter_router_lsa *)
568 OSPF6_LSA_HEADER_END (lsa->header);
569
570 ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf));
571 vty_out (vty, " Options: %s%s", buf, VNL);
572 vty_out (vty, " Metric: %lu%s",
573 (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
574 inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
575 vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
576
577 return 0;
578}
579
580/* Debug commands */
581DEFUN (debug_ospf6_abr,
582 debug_ospf6_abr_cmd,
583 "debug ospf6 abr",
584 DEBUG_STR
585 OSPF6_STR
586 "Debug OSPFv3 ABR function\n"
587 )
588{
589 OSPF6_DEBUG_ABR_ON ();
590 return CMD_SUCCESS;
591}
592
593DEFUN (no_debug_ospf6_abr,
594 no_debug_ospf6_abr_cmd,
595 "no debug ospf6 abr",
596 NO_STR
597 DEBUG_STR
598 OSPF6_STR
599 "Debug OSPFv3 ABR function\n"
600 )
601{
602 OSPF6_DEBUG_ABR_OFF ();
603 return CMD_SUCCESS;
604}
605
606int
607config_write_ospf6_debug_abr (struct vty *vty)
608{
609 if (IS_OSPF6_DEBUG_ABR)
610 vty_out (vty, "debug ospf6 abr%s", VNL);
611 return 0;
612}
613
614void
615install_element_ospf6_debug_abr ()
616{
617 install_element (ENABLE_NODE, &debug_ospf6_abr_cmd);
618 install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd);
619 install_element (CONFIG_NODE, &debug_ospf6_abr_cmd);
620 install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
621}
622
6452df09 623struct ospf6_lsa_handler inter_prefix_handler =
624{
625 OSPF6_LSTYPE_INTER_PREFIX,
626 "Inter-Prefix",
627 ospf6_inter_area_prefix_lsa_show
628};
629
630struct ospf6_lsa_handler inter_router_handler =
631{
632 OSPF6_LSTYPE_INTER_ROUTER,
633 "Inter-Router",
634 ospf6_inter_area_router_lsa_show
635};
636
049207c3 637void
638ospf6_abr_init ()
639{
6452df09 640 ospf6_install_lsa_handler (&inter_prefix_handler);
641 ospf6_install_lsa_handler (&inter_router_handler);
049207c3 642}
643
644