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