]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
*: reindent
[mirror_frr.git] / ospf6d / ospf6_abr.c
CommitLineData
049207c3 1/*
2 * Area Border Router function.
3 * Copyright (C) 2004 Yasuhiro Ohara
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
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
049207c3 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"
3b68735f 30#include "thread.h"
34956b31 31#include "plist.h"
32#include "filter.h"
049207c3 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"
6452df09 39#include "ospf6_message.h"
c3c0ac83 40#include "ospf6_zebra.h"
6452df09 41
049207c3 42#include "ospf6_top.h"
43#include "ospf6_area.h"
44#include "ospf6_interface.h"
6452df09 45#include "ospf6_neighbor.h"
46
6452df09 47#include "ospf6_flood.h"
3b68735f 48#include "ospf6_intra.h"
49#include "ospf6_abr.h"
049207c3 50#include "ospf6d.h"
51
52unsigned char conf_debug_ospf6_abr;
53
d62a17ae 54int ospf6_is_router_abr(struct ospf6 *o)
6452df09 55{
d62a17ae 56 struct listnode *node;
57 struct ospf6_area *oa;
58 int area_count = 0;
6452df09 59
d62a17ae 60 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa))
61 if (IS_AREA_ENABLED(oa))
62 area_count++;
6452df09 63
d62a17ae 64 if (area_count > 1)
65 return 1;
66 return 0;
6452df09 67}
68
d62a17ae 69static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
70 struct ospf6_area *area)
c3c0ac83 71{
d62a17ae 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;
c3c0ac83
DS
80}
81
d62a17ae 82static 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)
c3c0ac83 86{
d62a17ae 87 if (summary) {
88 ospf6_route_remove(summary, summary_table);
89 }
c3c0ac83 90
d62a17ae 91 if (old && !OSPF6_LSA_IS_MAXAGE(old))
92 ospf6_lsa_purge(old);
c3c0ac83
DS
93}
94
d62a17ae 95void ospf6_abr_enable_area(struct ospf6_area *area)
3b68735f 96{
d62a17ae 97 struct ospf6_area *oa;
98 struct listnode *node, *nnode;
3b68735f 99
d62a17ae 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);
3b68735f 103}
104
d62a17ae 105void ospf6_abr_disable_area(struct ospf6_area *area)
3b68735f 106{
d62a17ae 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);
3b68735f 138}
139
049207c3 140/* RFC 2328 12.4.3. Summary-LSAs */
ca1f4309
DS
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 */
d62a17ae 143int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
144 struct ospf6_area *area)
049207c3 145{
d62a17ae 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;
c3c0ac83 168 }
d62a17ae 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;
c3c0ac83 176 }
d62a17ae 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_NAME_OUT(area)) {
390 if (PREFIX_LIST_OUT(area) == NULL)
391 PREFIX_LIST_OUT(area) = prefix_list_lookup(
392 AFI_IP6, PREFIX_NAME_OUT(area));
393
394 if (PREFIX_LIST_OUT(area))
395 if (prefix_list_apply(PREFIX_LIST_OUT(area),
396 &route->prefix)
397 != PREFIX_PERMIT) {
398 if (is_debug) {
399 inet_ntop(AF_INET,
400 &(ADV_ROUTER_IN_PREFIX(
401 &route->prefix)),
402 buf, sizeof(buf));
403 zlog_debug(
404 "prefix %s was denied by filter-list out",
405 buf);
406 }
407 return 0;
408 }
c3c0ac83 409 }
d62a17ae 410
411 /* the route is going to be originated. store it in area's summary_table
412 */
413 if (summary == NULL) {
414 summary = ospf6_route_copy(route);
415 summary->path.origin.adv_router = area->ospf6->router_id;
416
417 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
418 summary->path.origin.type =
419 htons(OSPF6_LSTYPE_INTER_ROUTER);
420 summary->path.origin.id =
421 ADV_ROUTER_IN_PREFIX(&route->prefix);
422 } else {
423 summary->path.origin.type =
424 htons(OSPF6_LSTYPE_INTER_PREFIX);
425 summary->path.origin.id = ospf6_new_ls_id(
426 summary->path.origin.type,
427 summary->path.origin.adv_router, area->lsdb);
428 }
429 summary = ospf6_route_add(summary, summary_table);
430 } else {
431 summary->type = route->type;
432 monotime(&summary->changed);
c3c0ac83 433 }
d62a17ae 434
435 summary->path.router_bits = route->path.router_bits;
436 summary->path.options[0] = route->path.options[0];
437 summary->path.options[1] = route->path.options[1];
438 summary->path.options[2] = route->path.options[2];
439 summary->path.prefix_options = route->path.prefix_options;
440 summary->path.area_id = area->area_id;
441 summary->path.type = OSPF6_PATH_TYPE_INTER;
442 summary->path.subtype = route->path.subtype;
443 summary->path.cost = route->path.cost;
444 /* summary->nexthop[0] = route->nexthop[0]; */
445
446 /* prepare buffer */
447 memset(buffer, 0, sizeof(buffer));
448 lsa_header = (struct ospf6_lsa_header *)buffer;
449
450 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
451 router_lsa = (struct ospf6_inter_router_lsa
452 *)((caddr_t)lsa_header
453 + sizeof(struct ospf6_lsa_header));
454 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
455
456 /* Fill Inter-Area-Router-LSA */
457 router_lsa->options[0] = route->path.options[0];
458 router_lsa->options[1] = route->path.options[1];
459 router_lsa->options[2] = route->path.options[2];
460 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
461 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
462 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
463 } else {
464 prefix_lsa = (struct ospf6_inter_prefix_lsa
465 *)((caddr_t)lsa_header
466 + sizeof(struct ospf6_lsa_header));
467 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
468
469 /* Fill Inter-Area-Prefix-LSA */
470 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
471 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
472 prefix_lsa->prefix.prefix_options = route->path.prefix_options;
473
474 /* set Prefix */
475 memcpy(p, &route->prefix.u.prefix6,
476 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
477 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
478 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
479 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
c3c0ac83 480 }
d62a17ae 481
482 /* Fill LSA Header */
483 lsa_header->age = 0;
484 lsa_header->type = type;
485 lsa_header->id = summary->path.origin.id;
486 lsa_header->adv_router = area->ospf6->router_id;
487 lsa_header->seqnum =
488 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
489 lsa_header->adv_router, area->lsdb);
490 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
491
492 /* LSA checksum */
493 ospf6_lsa_checksum(lsa_header);
494
495 /* create LSA */
496 lsa = ospf6_lsa_create(lsa_header);
497
498 /* Originate */
499 ospf6_lsa_originate_area(lsa, area);
500
501 return 1;
6452df09 502}
503
d62a17ae 504void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
ca1f4309 505{
d62a17ae 506 struct listnode *node, *nnode;
507 struct ospf6_area *oa;
508 struct ospf6_route *range;
509
510 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
511 for (range = ospf6_route_head(oa->range_table); range;
512 range = ospf6_route_next(range))
513 OSPF6_ABR_RANGE_CLEAR_COST(range);
ca1f4309
DS
514}
515
d62a17ae 516static inline u_int32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
517 struct ospf6 *o)
6452df09 518{
d62a17ae 519 struct ospf6_route *ro;
520 u_int32_t cost = 0;
521
522 for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
523 ro = ospf6_route_match_next(&range->prefix, ro)) {
524 if (ro->path.area_id == range->path.area_id
525 && (ro->path.type == OSPF6_PATH_TYPE_INTRA)
526 && !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
527 cost = MAX(cost, ro->path.cost);
528 }
529
530 return cost;
ca1f4309
DS
531}
532
533static inline int
d62a17ae 534ospf6_abr_range_summary_needs_update(struct ospf6_route *range, u_int32_t cost)
ca1f4309 535{
d62a17ae 536 int redo_summary = 0;
537
538 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
539 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
540 redo_summary = 1;
541 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
542 if (range->path.cost != 0) {
543 range->path.cost = 0;
544 redo_summary = 1;
545 }
546 } else if (cost) {
547 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
548 && range->path.cost != range->path.u.cost_config)) {
549 range->path.cost = range->path.u.cost_config;
550 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
551 redo_summary = 1;
552 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
553 && range->path.cost != cost) {
554 range->path.cost = cost;
555 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
556 redo_summary = 1;
557 }
558 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
559 /* Cost is zero, meaning no active range */
560 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
561 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
562 redo_summary = 1;
c3c0ac83 563 }
d62a17ae 564
565 return (redo_summary);
ca1f4309
DS
566}
567
d62a17ae 568static void ospf6_abr_range_update(struct ospf6_route *range)
ca1f4309 569{
d62a17ae 570 u_int32_t cost = 0;
571 struct listnode *node, *nnode;
572 struct ospf6_area *oa;
573 int summary_orig = 0;
574
575 assert(range->type == OSPF6_DEST_TYPE_RANGE);
576
577 /* update range's cost and active flag */
578 cost = ospf6_abr_range_compute_cost(range, ospf6);
579
580 /* Non-zero cost is a proxy for active longer prefixes in this range.
581 * If there are active routes covered by this range AND either the
582 * configured
583 * cost has changed or the summarized cost has changed then redo
584 * summaries.
585 * Alternately, if there are no longer active prefixes and there are
586 * summary announcements, withdraw those announcements.
587 *
588 * The don't advertise code relies on the path.cost being set to UNSPEC
589 * to
590 * work the first time. Subsequent times the path.cost is not 0 anyway
591 * if there
592 * were active ranges.
593 */
594
595 if (ospf6_abr_range_summary_needs_update(range, cost)) {
596 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
597 summary_orig +=
598 ospf6_abr_originate_summary_to_area(range, oa);
599
600 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
601 && summary_orig) {
602 if (!CHECK_FLAG(range->flag,
603 OSPF6_ROUTE_BLACKHOLE_ADDED)) {
604 if (IS_OSPF6_DEBUG_ABR)
605 zlog_debug("Add discard route");
606
607 ospf6_zebra_add_discard(range);
608 }
609 } else {
610 /* Summary removed or no summary generated as no
611 * specifics exist */
612 if (CHECK_FLAG(range->flag,
613 OSPF6_ROUTE_BLACKHOLE_ADDED)) {
614 if (IS_OSPF6_DEBUG_ABR)
615 zlog_debug("Delete discard route");
616
617 ospf6_zebra_delete_discard(range);
618 }
619 }
c3c0ac83 620 }
049207c3 621}
622
d62a17ae 623void ospf6_abr_originate_summary(struct ospf6_route *route)
049207c3 624{
d62a17ae 625 struct listnode *node, *nnode;
626 struct ospf6_area *oa;
627 struct ospf6_route *range = NULL;
628
629 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
630 oa = ospf6_area_lookup(route->path.area_id, ospf6);
631 range = ospf6_route_lookup_bestmatch(&route->prefix,
632 oa->range_table);
633 if (range) {
634 ospf6_abr_range_update(range);
635 }
c3c0ac83 636 }
6452df09 637
d62a17ae 638 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
639 ospf6_abr_originate_summary_to_area(route, oa);
049207c3 640}
641
d62a17ae 642void ospf6_abr_defaults_to_stub(struct ospf6 *o)
ca1f4309 643{
d62a17ae 644 struct listnode *node, *nnode;
645 struct ospf6_area *oa;
646 struct ospf6_route *def, *route;
647
648 if (!o->backbone)
649 return;
650
651 def = ospf6_route_create();
652 def->type = OSPF6_DEST_TYPE_NETWORK;
653 def->prefix.family = AF_INET6;
654 def->prefix.prefixlen = 0;
655 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
656 def->type = OSPF6_DEST_TYPE_NETWORK;
657 def->path.type = OSPF6_PATH_TYPE_INTER;
658 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
659 def->path.area_id = o->backbone->area_id;
660
661 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
662 if (!IS_AREA_STUB(oa)) {
663 /* withdraw defaults when an area switches from stub to
664 * non-stub */
665 route = ospf6_route_lookup(&def->prefix,
666 oa->summary_prefix);
667 if (route
668 && (route->path.subtype == def->path.subtype)) {
669 if (IS_OSPF6_DEBUG_ABR)
670 zlog_debug(
671 "Withdrawing default route from non-stubby area %s",
672 oa->name);
673 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
674 ospf6_abr_originate_summary_to_area(def, oa);
675 }
676 } else {
677 /* announce defaults to stubby areas */
678 if (IS_OSPF6_DEBUG_ABR)
679 zlog_debug(
680 "Announcing default route into stubby area %s",
681 oa->name);
682 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
683 ospf6_abr_originate_summary_to_area(def, oa);
684 }
ca1f4309 685 }
d62a17ae 686 ospf6_route_delete(def);
ca1f4309
DS
687}
688
049207c3 689/* RFC 2328 16.2. Calculating the inter-area routes */
d62a17ae 690void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
049207c3 691{
d62a17ae 692 struct prefix prefix, abr_prefix;
693 struct ospf6_route_table *table = NULL;
694 struct ospf6_route *range, *route, *old = NULL;
695 struct ospf6_route *abr_entry;
696 u_char type = 0;
697 char options[3] = {0, 0, 0};
698 u_int8_t prefix_options = 0;
699 u_int32_t cost = 0;
700 u_char router_bits = 0;
701 char buf[PREFIX2STR_BUFFER];
702 int is_debug = 0;
703 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
704 struct ospf6_inter_router_lsa *router_lsa = NULL;
705
706 memset(&prefix, 0, sizeof(prefix));
707
708 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
709 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
710 is_debug++;
711 zlog_debug("Examin %s in area %s", lsa->name, oa->name);
712 }
713
714 prefix_lsa =
715 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
716 lsa->header);
717 prefix.family = AF_INET6;
718 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
719 ospf6_prefix_in6_addr(&prefix.u.prefix6, &prefix_lsa->prefix);
720 if (is_debug)
721 prefix2str(&prefix, buf, sizeof(buf));
722 table = oa->ospf6->route_table;
723 type = OSPF6_DEST_TYPE_NETWORK;
724 prefix_options = prefix_lsa->prefix.prefix_options;
725 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
726 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
727 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
728 is_debug++;
729 zlog_debug("Examin %s in area %s", lsa->name, oa->name);
730 }
731
732 router_lsa =
733 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
734 lsa->header);
735 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
736 &prefix);
737 if (is_debug)
738 inet_ntop(AF_INET, &router_lsa->router_id, buf,
739 sizeof(buf));
740
741 table = oa->ospf6->brouter_table;
742 type = OSPF6_DEST_TYPE_ROUTER;
743 options[0] = router_lsa->options[0];
744 options[1] = router_lsa->options[1];
745 options[2] = router_lsa->options[2];
746 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
747 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
748 } else
749 assert(0);
750
751 /* Find existing route */
752 route = ospf6_route_lookup(&prefix, table);
753 if (route)
754 ospf6_route_lock(route);
755 while (route && ospf6_route_is_prefix(&prefix, route)) {
756 if (route->path.area_id == oa->area_id
757 && route->path.origin.type == lsa->header->type
758 && route->path.origin.id == lsa->header->id
759 && route->path.origin.adv_router == lsa->header->adv_router
760 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED))
761 old = route;
762 route = ospf6_route_next(route);
763 }
764 if (route)
765 ospf6_route_unlock(route);
766
767 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
768 if (cost == OSPF_LS_INFINITY) {
769 if (is_debug)
770 zlog_debug("cost is LS_INFINITY, ignore");
771 if (old)
772 ospf6_route_remove(old, table);
773 return;
774 }
775 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
776 if (is_debug)
777 zlog_debug("LSA is MaxAge, ignore");
778 if (old)
779 ospf6_route_remove(old, table);
780 return;
781 }
782
783 /* (2) if the LSA is self-originated, ignore */
784 if (lsa->header->adv_router == oa->ospf6->router_id) {
785 if (is_debug)
786 zlog_debug("LSA is self-originated, ignore");
787 if (old)
788 ospf6_route_remove(old, table);
789 return;
01879114 790 }
d62a17ae 791
792 /* (3) if the prefix is equal to an active configured address range */
793 /* or if the NU bit is set in the prefix */
794 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
795 range = ospf6_route_lookup(&prefix, oa->range_table);
796 if (range) {
797 if (is_debug)
798 zlog_debug(
799 "Prefix is equal to address range, ignore");
800 if (old)
801 ospf6_route_remove(old, table);
802 return;
803 }
804
805 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
806 OSPF6_PREFIX_OPTION_NU)
807 || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
808 OSPF6_PREFIX_OPTION_LA)) {
809 if (is_debug)
810 zlog_debug("Prefix has NU/LA bit set, ignore");
811 if (old)
812 ospf6_route_remove(old, table);
813 return;
814 }
01879114 815 }
d62a17ae 816
817 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
818 /* To pass test suites */
819 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
820 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
821 if (is_debug)
822 zlog_debug("Prefix has NU/LA bit set, ignore");
823 if (old)
824 ospf6_route_remove(old, table);
825
826 return;
827 }
828 /* Avoid infinite recursion if someone has maliciously announced
829 an
830 Inter-Router LSA for an ABR
831 */
832 if (lsa->header->adv_router == router_lsa->router_id) {
833 if (is_debug)
834 zlog_debug(
835 "Ignorning Inter-Router LSA for an ABR (%s)",
836 buf);
837 if (old)
838 ospf6_route_remove(old, table);
839
840 return;
841 }
842 }
843
844 /* (4) if the routing table entry for the ABR does not exist */
845 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
846 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
847 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
848 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
849 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
850 if (is_debug)
851 zlog_debug("ABR router entry does not exist, ignore");
852 if (old)
853 ospf6_route_remove(old, table);
854 return;
855 }
856
857 /* Check import list */
858 if (IMPORT_NAME(oa)) {
859 if (IMPORT_LIST(oa) == NULL)
860 IMPORT_LIST(oa) =
861 access_list_lookup(AFI_IP6, IMPORT_NAME(oa));
862
863 if (IMPORT_LIST(oa))
864 if (access_list_apply(IMPORT_LIST(oa), &prefix)
865 == FILTER_DENY) {
866 if (is_debug)
867 zlog_debug(
868 "Prefix was denied by import-list");
869 if (old)
870 ospf6_route_remove(old, table);
871 return;
872 }
873 }
874
875 /* Check input prefix-list */
876 if (PREFIX_NAME_IN(oa)) {
877 if (PREFIX_LIST_IN(oa) == NULL)
878 PREFIX_LIST_IN(oa) =
879 prefix_list_lookup(AFI_IP6, PREFIX_NAME_IN(oa));
880
881 if (PREFIX_LIST_IN(oa))
882 if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
883 != PREFIX_PERMIT) {
884 if (is_debug)
885 zlog_debug(
886 "Prefix was denied by prefix-list");
887 if (old)
888 ospf6_route_remove(old, table);
889 return;
890 }
891 }
892
893 /* (5),(6): the path preference is handled by the sorting
894 in the routing table. Always install the path by substituting
895 old route (if any). */
896 if (old)
897 route = ospf6_route_copy(old);
898 else
899 route = ospf6_route_create();
900
901 route->type = type;
902 route->prefix = prefix;
903 route->path.origin.type = lsa->header->type;
904 route->path.origin.id = lsa->header->id;
905 route->path.origin.adv_router = lsa->header->adv_router;
906 route->path.router_bits = router_bits;
907 route->path.options[0] = options[0];
908 route->path.options[1] = options[1];
909 route->path.options[2] = options[2];
910 route->path.prefix_options = prefix_options;
911 route->path.area_id = oa->area_id;
912 route->path.type = OSPF6_PATH_TYPE_INTER;
913 route->path.cost = abr_entry->path.cost + cost;
914
915 ospf6_route_copy_nexthops(route, abr_entry);
916
917 /* (7) If the routes are identical, copy the next hops over to existing
918 route. ospf6's route table implementation will otherwise string both
919 routes, but keep the older one as the best route since the routes
920 are identical.
921 */
922 old = ospf6_route_lookup(&prefix, table);
923
924 if (old && (ospf6_route_cmp(route, old) == 0)) {
925 ospf6_route_merge_nexthops(old, route);
926 /* Update RIB/FIB */
927 if (table->hook_add)
928 (*table->hook_add)(old);
929
930 /* Delete new route */
931 ospf6_route_delete(route);
932 } else {
933 if (is_debug)
934 zlog_debug("Install route: %s", buf);
935 /* ospf6_ia_add_nw_route (table, &prefix, route); */
936 ospf6_route_add(route, table);
c3c0ac83 937 }
049207c3 938}
939
d62a17ae 940void ospf6_abr_examin_brouter(u_int32_t router_id)
ccb59b11 941{
d62a17ae 942 struct ospf6_lsa *lsa;
943 struct ospf6_area *oa;
944 u_int16_t type;
945
946 if (ospf6_is_router_abr(ospf6))
947 oa = ospf6->backbone;
948 else
949 oa = listgetdata(listhead(ospf6->area_list));
950
951 /*
952 * It is possible to designate a non backbone
953 * area first. If that is the case safely
954 * fall out of this function.
955 */
956 if (oa == NULL)
957 return;
958
959 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
960 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
961 ospf6_abr_examin_summary(lsa, oa);
962
963 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
964 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
965 ospf6_abr_examin_summary(lsa, oa);
ccb59b11 966}
967
d62a17ae 968void ospf6_abr_reimport(struct ospf6_area *oa)
34956b31 969{
d62a17ae 970 struct ospf6_lsa *lsa;
971 u_int16_t type;
34956b31 972
d62a17ae 973 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
974 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
975 ospf6_abr_examin_summary(lsa, oa);
34956b31 976
d62a17ae 977 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
978 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
979 ospf6_abr_examin_summary(lsa, oa);
34956b31 980}
981
d62a17ae 982void ospf6_abr_prefix_resummarize(struct ospf6 *o)
ca1f4309 983{
d62a17ae 984 struct ospf6_route *route;
ca1f4309 985
d62a17ae 986 if (IS_OSPF6_DEBUG_ABR)
987 zlog_debug("Re-examining Inter-Prefix Summaries");
ca1f4309 988
d62a17ae 989 for (route = ospf6_route_head(o->route_table); route;
990 route = ospf6_route_next(route))
991 ospf6_abr_originate_summary(route);
ca1f4309 992
d62a17ae 993 if (IS_OSPF6_DEBUG_ABR)
994 zlog_debug("Finished re-examining Inter-Prefix Summaries");
ca1f4309 995}
34956b31 996
6b0655a2 997
049207c3 998/* Display functions */
d62a17ae 999static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1000 char *buf, int buflen,
1001 int pos)
e68a6767 1002{
d62a17ae 1003 struct ospf6_inter_prefix_lsa *prefix_lsa;
1004 struct in6_addr in6;
1005
1006 if (lsa != NULL) {
1007 prefix_lsa =
1008 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1009 lsa->header);
1010
1011 ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix);
1012 if (buf) {
1013 inet_ntop(AF_INET6, &in6, buf, buflen);
1014 sprintf(&buf[strlen(buf)], "/%d",
1015 prefix_lsa->prefix.prefix_length);
1016 }
e68a6767 1017 }
e68a6767 1018
d62a17ae 1019 return (buf);
e68a6767
DD
1020}
1021
d62a17ae 1022static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1023 struct ospf6_lsa *lsa)
049207c3 1024{
d62a17ae 1025 struct ospf6_inter_prefix_lsa *prefix_lsa;
1026 char buf[INET6_ADDRSTRLEN];
049207c3 1027
d62a17ae 1028 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1029 lsa->header);
049207c3 1030
d62a17ae 1031 vty_out(vty, " Metric: %lu\n",
1032 (u_long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
049207c3 1033
d62a17ae 1034 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf,
1035 sizeof(buf));
1036 vty_out(vty, " Prefix Options: %s\n", buf);
049207c3 1037
d62a17ae 1038 vty_out(vty, " Prefix: %s\n",
1039 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf,
1040 sizeof(buf), 0));
049207c3 1041
d62a17ae 1042 return 0;
049207c3 1043}
1044
d62a17ae 1045static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1046 char *buf, int buflen,
1047 int pos)
e68a6767 1048{
d62a17ae 1049 struct ospf6_inter_router_lsa *router_lsa;
e68a6767 1050
d62a17ae 1051 if (lsa != NULL) {
1052 router_lsa =
1053 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1054 lsa->header);
e68a6767
DD
1055
1056
d62a17ae 1057 if (buf)
1058 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1059 }
e68a6767 1060
d62a17ae 1061 return (buf);
e68a6767
DD
1062}
1063
d62a17ae 1064static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1065 struct ospf6_lsa *lsa)
049207c3 1066{
d62a17ae 1067 struct ospf6_inter_router_lsa *router_lsa;
1068 char buf[64];
049207c3 1069
d62a17ae 1070 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1071 lsa->header);
049207c3 1072
d62a17ae 1073 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1074 vty_out(vty, " Options: %s\n", buf);
1075 vty_out(vty, " Metric: %lu\n",
1076 (u_long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
e68a6767 1077
d62a17ae 1078 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1079 vty_out(vty, " Destination Router ID: %s\n", buf);
049207c3 1080
d62a17ae 1081 return 0;
049207c3 1082}
1083
1084/* Debug commands */
1085DEFUN (debug_ospf6_abr,
1086 debug_ospf6_abr_cmd,
1087 "debug ospf6 abr",
1088 DEBUG_STR
1089 OSPF6_STR
1090 "Debug OSPFv3 ABR function\n"
1091 )
1092{
d62a17ae 1093 OSPF6_DEBUG_ABR_ON();
1094 return CMD_SUCCESS;
049207c3 1095}
1096
1097DEFUN (no_debug_ospf6_abr,
1098 no_debug_ospf6_abr_cmd,
1099 "no debug ospf6 abr",
1100 NO_STR
1101 DEBUG_STR
1102 OSPF6_STR
1103 "Debug OSPFv3 ABR function\n"
1104 )
1105{
d62a17ae 1106 OSPF6_DEBUG_ABR_OFF();
1107 return CMD_SUCCESS;
049207c3 1108}
1109
d62a17ae 1110int config_write_ospf6_debug_abr(struct vty *vty)
049207c3 1111{
d62a17ae 1112 if (IS_OSPF6_DEBUG_ABR)
1113 vty_out(vty, "debug ospf6 abr\n");
1114 return 0;
049207c3 1115}
1116
d62a17ae 1117void install_element_ospf6_debug_abr(void)
049207c3 1118{
d62a17ae 1119 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1120 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1121 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1122 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
049207c3 1123}
1124
d62a17ae 1125struct ospf6_lsa_handler inter_prefix_handler = {
1126 OSPF6_LSTYPE_INTER_PREFIX,
1127 "Inter-Prefix",
1128 "IAP",
1129 ospf6_inter_area_prefix_lsa_show,
1130 ospf6_inter_area_prefix_lsa_get_prefix_str,
6452df09 1131};
1132
d62a17ae 1133struct ospf6_lsa_handler inter_router_handler = {
1134 OSPF6_LSTYPE_INTER_ROUTER,
1135 "Inter-Router",
1136 "IAR",
1137 ospf6_inter_area_router_lsa_show,
1138 ospf6_inter_area_router_lsa_get_prefix_str,
6452df09 1139};
1140
d62a17ae 1141void ospf6_abr_init(void)
049207c3 1142{
d62a17ae 1143 ospf6_install_lsa_handler(&inter_prefix_handler);
1144 ospf6_install_lsa_handler(&inter_router_handler);
049207c3 1145}