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