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