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