]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_abr.c
tools, doc: update checkpatch for u_int_*
[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 */
427f8e61
DL
389 if (PREFIX_LIST_OUT(area))
390 if (prefix_list_apply(PREFIX_LIST_OUT(area), &route->prefix)
391 != PREFIX_PERMIT) {
392 if (is_debug) {
996c9314
LB
393 inet_ntop(
394 AF_INET,
395 &(ADV_ROUTER_IN_PREFIX(&route->prefix)),
396 buf, sizeof(buf));
427f8e61
DL
397 zlog_debug(
398 "prefix %s was denied by filter-list out",
399 buf);
d62a17ae 400 }
427f8e61
DL
401 return 0;
402 }
d62a17ae 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);
c3c0ac83 426 }
d62a17ae 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);
c3c0ac83 473 }
d62a17ae 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;
6452df09 495}
496
d62a17ae 497void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
ca1f4309 498{
d62a17ae 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);
ca1f4309
DS
507}
508
d62a17ae 509static inline u_int32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
510 struct ospf6 *o)
6452df09 511{
d62a17ae 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;
ca1f4309
DS
524}
525
526static inline int
d62a17ae 527ospf6_abr_range_summary_needs_update(struct ospf6_route *range, u_int32_t cost)
ca1f4309 528{
d62a17ae 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;
c3c0ac83 556 }
d62a17ae 557
558 return (redo_summary);
ca1f4309
DS
559}
560
d62a17ae 561static void ospf6_abr_range_update(struct ospf6_route *range)
ca1f4309 562{
d62a17ae 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 }
c3c0ac83 613 }
049207c3 614}
615
d62a17ae 616void ospf6_abr_originate_summary(struct ospf6_route *route)
049207c3 617{
d62a17ae 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 }
c3c0ac83 629 }
6452df09 630
d62a17ae 631 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
632 ospf6_abr_originate_summary_to_area(route, oa);
049207c3 633}
634
d62a17ae 635void ospf6_abr_defaults_to_stub(struct ospf6 *o)
ca1f4309 636{
d62a17ae 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 }
ca1f4309 678 }
d62a17ae 679 ospf6_route_delete(def);
ca1f4309
DS
680}
681
049207c3 682/* RFC 2328 16.2. Calculating the inter-area routes */
d62a17ae 683void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
049207c3 684{
d62a17ae 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;
01879114 783 }
d62a17ae 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 }
01879114 808 }
d62a17ae 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 */
427f8e61
DL
869 if (PREFIX_LIST_IN(oa))
870 if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
871 != PREFIX_PERMIT) {
872 if (is_debug)
996c9314 873 zlog_debug("Prefix was denied by prefix-list");
427f8e61
DL
874 if (old)
875 ospf6_route_remove(old, table);
876 return;
877 }
d62a17ae 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
064d4355 903
d62a17ae 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);
064d4355
CS
913
914 if (is_debug)
c601fa3f
CS
915 zlog_debug("%s: Update route: %s old cost %u new cost %u nh count %u",
916 __PRETTY_FUNCTION__,
917 buf, old->path.cost, route->path.cost,
996c9314 918 listcount(route->nh_list));
064d4355 919
d62a17ae 920 /* Update RIB/FIB */
921 if (table->hook_add)
922 (*table->hook_add)(old);
923
924 /* Delete new route */
925 ospf6_route_delete(route);
926 } else {
927 if (is_debug)
c601fa3f
CS
928 zlog_debug("%s: Install route: %s cost %u nh count %u",
929 __PRETTY_FUNCTION__, buf, route->path.cost,
996c9314 930 listcount(route->nh_list));
d62a17ae 931 /* ospf6_ia_add_nw_route (table, &prefix, route); */
932 ospf6_route_add(route, table);
c3c0ac83 933 }
049207c3 934}
935
d62a17ae 936void ospf6_abr_examin_brouter(u_int32_t router_id)
ccb59b11 937{
d62a17ae 938 struct ospf6_lsa *lsa;
939 struct ospf6_area *oa;
940 u_int16_t type;
941
942 if (ospf6_is_router_abr(ospf6))
943 oa = ospf6->backbone;
944 else
945 oa = listgetdata(listhead(ospf6->area_list));
946
947 /*
948 * It is possible to designate a non backbone
949 * area first. If that is the case safely
950 * fall out of this function.
951 */
952 if (oa == NULL)
953 return;
954
955 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
956 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
957 ospf6_abr_examin_summary(lsa, oa);
958
959 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
960 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
961 ospf6_abr_examin_summary(lsa, oa);
ccb59b11 962}
963
d62a17ae 964void ospf6_abr_reimport(struct ospf6_area *oa)
34956b31 965{
d62a17ae 966 struct ospf6_lsa *lsa;
967 u_int16_t type;
34956b31 968
d62a17ae 969 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
970 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
971 ospf6_abr_examin_summary(lsa, oa);
34956b31 972
d62a17ae 973 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
974 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
975 ospf6_abr_examin_summary(lsa, oa);
34956b31 976}
977
d62a17ae 978void ospf6_abr_prefix_resummarize(struct ospf6 *o)
ca1f4309 979{
d62a17ae 980 struct ospf6_route *route;
ca1f4309 981
d62a17ae 982 if (IS_OSPF6_DEBUG_ABR)
983 zlog_debug("Re-examining Inter-Prefix Summaries");
ca1f4309 984
d62a17ae 985 for (route = ospf6_route_head(o->route_table); route;
986 route = ospf6_route_next(route))
987 ospf6_abr_originate_summary(route);
ca1f4309 988
d62a17ae 989 if (IS_OSPF6_DEBUG_ABR)
990 zlog_debug("Finished re-examining Inter-Prefix Summaries");
ca1f4309 991}
34956b31 992
6b0655a2 993
049207c3 994/* Display functions */
d62a17ae 995static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
996 char *buf, int buflen,
997 int pos)
e68a6767 998{
d62a17ae 999 struct ospf6_inter_prefix_lsa *prefix_lsa;
1000 struct in6_addr in6;
1001
1002 if (lsa != NULL) {
1003 prefix_lsa =
1004 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1005 lsa->header);
1006
1007 ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix);
1008 if (buf) {
1009 inet_ntop(AF_INET6, &in6, buf, buflen);
1010 sprintf(&buf[strlen(buf)], "/%d",
1011 prefix_lsa->prefix.prefix_length);
1012 }
e68a6767 1013 }
e68a6767 1014
d62a17ae 1015 return (buf);
e68a6767
DD
1016}
1017
d62a17ae 1018static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1019 struct ospf6_lsa *lsa)
049207c3 1020{
d62a17ae 1021 struct ospf6_inter_prefix_lsa *prefix_lsa;
1022 char buf[INET6_ADDRSTRLEN];
049207c3 1023
d62a17ae 1024 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1025 lsa->header);
049207c3 1026
d62a17ae 1027 vty_out(vty, " Metric: %lu\n",
1028 (u_long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
049207c3 1029
d62a17ae 1030 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf,
1031 sizeof(buf));
1032 vty_out(vty, " Prefix Options: %s\n", buf);
049207c3 1033
d62a17ae 1034 vty_out(vty, " Prefix: %s\n",
1035 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf,
1036 sizeof(buf), 0));
049207c3 1037
d62a17ae 1038 return 0;
049207c3 1039}
1040
d62a17ae 1041static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1042 char *buf, int buflen,
1043 int pos)
e68a6767 1044{
d62a17ae 1045 struct ospf6_inter_router_lsa *router_lsa;
e68a6767 1046
d62a17ae 1047 if (lsa != NULL) {
1048 router_lsa =
1049 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1050 lsa->header);
e68a6767
DD
1051
1052
d62a17ae 1053 if (buf)
1054 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1055 }
e68a6767 1056
d62a17ae 1057 return (buf);
e68a6767
DD
1058}
1059
d62a17ae 1060static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1061 struct ospf6_lsa *lsa)
049207c3 1062{
d62a17ae 1063 struct ospf6_inter_router_lsa *router_lsa;
1064 char buf[64];
049207c3 1065
d62a17ae 1066 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1067 lsa->header);
049207c3 1068
d62a17ae 1069 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1070 vty_out(vty, " Options: %s\n", buf);
1071 vty_out(vty, " Metric: %lu\n",
1072 (u_long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
e68a6767 1073
d62a17ae 1074 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1075 vty_out(vty, " Destination Router ID: %s\n", buf);
049207c3 1076
d62a17ae 1077 return 0;
049207c3 1078}
1079
1080/* Debug commands */
1081DEFUN (debug_ospf6_abr,
1082 debug_ospf6_abr_cmd,
1083 "debug ospf6 abr",
1084 DEBUG_STR
1085 OSPF6_STR
1086 "Debug OSPFv3 ABR function\n"
1087 )
1088{
d62a17ae 1089 OSPF6_DEBUG_ABR_ON();
1090 return CMD_SUCCESS;
049207c3 1091}
1092
1093DEFUN (no_debug_ospf6_abr,
1094 no_debug_ospf6_abr_cmd,
1095 "no debug ospf6 abr",
1096 NO_STR
1097 DEBUG_STR
1098 OSPF6_STR
1099 "Debug OSPFv3 ABR function\n"
1100 )
1101{
d62a17ae 1102 OSPF6_DEBUG_ABR_OFF();
1103 return CMD_SUCCESS;
049207c3 1104}
1105
d62a17ae 1106int config_write_ospf6_debug_abr(struct vty *vty)
049207c3 1107{
d62a17ae 1108 if (IS_OSPF6_DEBUG_ABR)
1109 vty_out(vty, "debug ospf6 abr\n");
1110 return 0;
049207c3 1111}
1112
d62a17ae 1113void install_element_ospf6_debug_abr(void)
049207c3 1114{
d62a17ae 1115 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1116 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1117 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1118 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
049207c3 1119}
1120
d62a17ae 1121struct ospf6_lsa_handler inter_prefix_handler = {
3981b5c7
VJ
1122 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1123 .lh_name = "Inter-Prefix",
1124 .lh_short_name = "IAP",
1125 .lh_show = ospf6_inter_area_prefix_lsa_show,
1126 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
996c9314 1127 .lh_debug = 0};
6452df09 1128
d62a17ae 1129struct ospf6_lsa_handler inter_router_handler = {
3981b5c7
VJ
1130 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1131 .lh_name = "Inter-Router",
1132 .lh_short_name = "IAR",
1133 .lh_show = ospf6_inter_area_router_lsa_show,
1134 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
996c9314 1135 .lh_debug = 0};
6452df09 1136
d62a17ae 1137void ospf6_abr_init(void)
049207c3 1138{
d62a17ae 1139 ospf6_install_lsa_handler(&inter_prefix_handler);
1140 ospf6_install_lsa_handler(&inter_router_handler);
049207c3 1141}