]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_abr.c
Merge pull request #2195 from qlyoung/docuser
[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 uint16_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 uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
510 struct ospf6 *o)
511 {
512 struct ospf6_route *ro;
513 uint32_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, uint32_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 uint32_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, *old_route;
688 struct ospf6_route *abr_entry;
689 uint8_t type = 0;
690 char options[3] = {0, 0, 0};
691 uint8_t prefix_options = 0;
692 uint32_t cost = 0;
693 uint8_t 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 bool old_entry_updated = false;
699
700 memset(&prefix, 0, sizeof(prefix));
701
702 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
703 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
704 is_debug++;
705 zlog_debug("%s: Examin %s in area %s",
706 __PRETTY_FUNCTION__, lsa->name, oa->name);
707 }
708
709 prefix_lsa =
710 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
711 lsa->header);
712 prefix.family = AF_INET6;
713 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
714 ospf6_prefix_in6_addr(&prefix.u.prefix6, &prefix_lsa->prefix);
715 if (is_debug)
716 prefix2str(&prefix, buf, sizeof(buf));
717 table = oa->ospf6->route_table;
718 type = OSPF6_DEST_TYPE_NETWORK;
719 prefix_options = prefix_lsa->prefix.prefix_options;
720 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
721 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
722 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
723 is_debug++;
724 zlog_debug("%s: Examin %s in area %s",
725 __PRETTY_FUNCTION__, lsa->name, oa->name);
726 }
727
728 router_lsa =
729 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
730 lsa->header);
731 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
732 &prefix);
733 if (is_debug)
734 inet_ntop(AF_INET, &router_lsa->router_id, buf,
735 sizeof(buf));
736
737 table = oa->ospf6->brouter_table;
738 type = OSPF6_DEST_TYPE_ROUTER;
739 options[0] = router_lsa->options[0];
740 options[1] = router_lsa->options[1];
741 options[2] = router_lsa->options[2];
742 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
743 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
744 } else
745 assert(0);
746
747 /* Find existing route */
748 route = ospf6_route_lookup(&prefix, table);
749 if (route)
750 ospf6_route_lock(route);
751 while (route && ospf6_route_is_prefix(&prefix, route)) {
752 if (route->path.area_id == oa->area_id
753 && route->path.origin.type == lsa->header->type
754 && route->path.origin.id == lsa->header->id
755 && route->path.origin.adv_router == lsa->header->adv_router
756 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED))
757 old = route;
758 route = ospf6_route_next(route);
759 }
760 if (route)
761 ospf6_route_unlock(route);
762
763 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
764 if (cost == OSPF_LS_INFINITY) {
765 if (is_debug)
766 zlog_debug("cost is LS_INFINITY, ignore");
767 if (old)
768 ospf6_route_remove(old, table);
769 return;
770 }
771 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
772 if (is_debug)
773 zlog_debug("%s: LSA %s is MaxAge, ignore",
774 __PRETTY_FUNCTION__, lsa->name);
775 if (old)
776 ospf6_route_remove(old, table);
777 return;
778 }
779
780 /* (2) if the LSA is self-originated, ignore */
781 if (lsa->header->adv_router == oa->ospf6->router_id) {
782 if (is_debug)
783 zlog_debug("LSA is self-originated, ignore");
784 if (old)
785 ospf6_route_remove(old, table);
786 return;
787 }
788
789 /* (3) if the prefix is equal to an active configured address range */
790 /* or if the NU bit is set in the prefix */
791 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
792 /* must have been set in previous block */
793 assert(prefix_lsa);
794
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 }
815 }
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("%s: ABR router entry does not exist, ignore",
852 __PRETTY_FUNCTION__);
853 if (old) {
854 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
855 oa->intra_brouter_calc) {
856 if (is_debug)
857 zlog_debug(
858 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
859 __PRETTY_FUNCTION__, buf,
860 (void *)old);
861 } else {
862 if (is_debug)
863 zlog_debug("%s: remove old entry: %s %p ",
864 __PRETTY_FUNCTION__, buf,
865 (void *)old);
866 ospf6_route_remove(old, table);
867 }
868 }
869 return;
870 }
871
872 /* Check import list */
873 if (IMPORT_NAME(oa)) {
874 if (IMPORT_LIST(oa) == NULL)
875 IMPORT_LIST(oa) =
876 access_list_lookup(AFI_IP6, IMPORT_NAME(oa));
877
878 if (IMPORT_LIST(oa))
879 if (access_list_apply(IMPORT_LIST(oa), &prefix)
880 == FILTER_DENY) {
881 if (is_debug)
882 zlog_debug(
883 "Prefix was denied by import-list");
884 if (old)
885 ospf6_route_remove(old, table);
886 return;
887 }
888 }
889
890 /* Check input prefix-list */
891 if (PREFIX_LIST_IN(oa))
892 if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
893 != PREFIX_PERMIT) {
894 if (is_debug)
895 zlog_debug("Prefix was denied by prefix-list");
896 if (old)
897 ospf6_route_remove(old, table);
898 return;
899 }
900
901 /* (5),(6): the path preference is handled by the sorting
902 in the routing table. Always install the path by substituting
903 old route (if any). */
904 if (old)
905 route = ospf6_route_copy(old);
906 else
907 route = ospf6_route_create();
908
909 route->type = type;
910 route->prefix = prefix;
911 route->path.origin.type = lsa->header->type;
912 route->path.origin.id = lsa->header->id;
913 route->path.origin.adv_router = lsa->header->adv_router;
914 route->path.router_bits = router_bits;
915 route->path.options[0] = options[0];
916 route->path.options[1] = options[1];
917 route->path.options[2] = options[2];
918 route->path.prefix_options = prefix_options;
919 route->path.area_id = oa->area_id;
920 route->path.type = OSPF6_PATH_TYPE_INTER;
921 route->path.cost = abr_entry->path.cost + cost;
922
923 /* Inter abr_entry is same as brouter.
924 * Avoid duplicate nexthops to brouter and its
925 * learnt route. i.e. use merge nexthops.
926 */
927 ospf6_route_merge_nexthops(route, abr_entry);
928
929 /* (7) If the routes are identical, copy the next hops over to existing
930 route. ospf6's route table implementation will otherwise string both
931 routes, but keep the older one as the best route since the routes
932 are identical.
933 */
934 old = ospf6_route_lookup(&prefix, table);
935
936 for (old_route = old; old_route; old_route = old_route->next) {
937 if (!ospf6_route_is_same(old_route, route) ||
938 (old_route->type != route->type) ||
939 (old_route->path.type != route->path.type))
940 continue;
941
942 if ((ospf6_route_cmp(route, old_route) != 0)) {
943 if (is_debug) {
944 prefix2str(&prefix, buf, sizeof(buf));
945 zlog_debug("%s: old %p %s cost %u new route cost %u are not same",
946 __PRETTY_FUNCTION__,
947 (void *)old_route, buf,
948 old_route->path.cost,
949 route->path.cost);
950 }
951 continue;
952 }
953
954 old_entry_updated = true;
955 ospf6_route_merge_nexthops(old, route);
956 if (is_debug)
957 zlog_debug("%s: Update route: %s old cost %u new cost %u nh %u",
958 __PRETTY_FUNCTION__,
959 buf, old->path.cost, route->path.cost,
960 listcount(route->nh_list));
961
962 /* Update RIB/FIB */
963 if (table->hook_add)
964 (*table->hook_add)(old);
965
966 /* Delete new route */
967 ospf6_route_delete(route);
968 break;
969 }
970
971 if (old_entry_updated == false) {
972 if (is_debug)
973 zlog_debug("%s: Install route: %s cost %u nh %u",
974 __PRETTY_FUNCTION__, buf, route->path.cost,
975 listcount(route->nh_list));
976 /* ospf6_ia_add_nw_route (table, &prefix, route); */
977 ospf6_route_add(route, table);
978 }
979 }
980
981 void ospf6_abr_examin_brouter(uint32_t router_id)
982 {
983 struct ospf6_lsa *lsa;
984 struct ospf6_area *oa;
985 uint16_t type;
986
987 if (ospf6_is_router_abr(ospf6))
988 oa = ospf6->backbone;
989 else
990 oa = listgetdata(listhead(ospf6->area_list));
991
992 /*
993 * It is possible to designate a non backbone
994 * area first. If that is the case safely
995 * fall out of this function.
996 */
997 if (oa == NULL)
998 return;
999
1000 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1001 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1002 ospf6_abr_examin_summary(lsa, oa);
1003
1004 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1005 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1006 ospf6_abr_examin_summary(lsa, oa);
1007 }
1008
1009 void ospf6_abr_reimport(struct ospf6_area *oa)
1010 {
1011 struct ospf6_lsa *lsa;
1012 uint16_t type;
1013
1014 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1015 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1016 ospf6_abr_examin_summary(lsa, oa);
1017
1018 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1019 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
1020 ospf6_abr_examin_summary(lsa, oa);
1021 }
1022
1023 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
1024 {
1025 struct ospf6_route *route;
1026
1027 if (IS_OSPF6_DEBUG_ABR)
1028 zlog_debug("Re-examining Inter-Prefix Summaries");
1029
1030 for (route = ospf6_route_head(o->route_table); route;
1031 route = ospf6_route_next(route))
1032 ospf6_abr_originate_summary(route);
1033
1034 if (IS_OSPF6_DEBUG_ABR)
1035 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1036 }
1037
1038
1039 /* Display functions */
1040 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1041 char *buf, int buflen,
1042 int pos)
1043 {
1044 struct ospf6_inter_prefix_lsa *prefix_lsa;
1045 struct in6_addr in6;
1046
1047 if (lsa != NULL) {
1048 prefix_lsa =
1049 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1050 lsa->header);
1051
1052 ospf6_prefix_in6_addr(&in6, &prefix_lsa->prefix);
1053 if (buf) {
1054 inet_ntop(AF_INET6, &in6, buf, buflen);
1055 sprintf(&buf[strlen(buf)], "/%d",
1056 prefix_lsa->prefix.prefix_length);
1057 }
1058 }
1059
1060 return (buf);
1061 }
1062
1063 static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1064 struct ospf6_lsa *lsa)
1065 {
1066 struct ospf6_inter_prefix_lsa *prefix_lsa;
1067 char buf[INET6_ADDRSTRLEN];
1068
1069 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1070 lsa->header);
1071
1072 vty_out(vty, " Metric: %lu\n",
1073 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1074
1075 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf,
1076 sizeof(buf));
1077 vty_out(vty, " Prefix Options: %s\n", buf);
1078
1079 vty_out(vty, " Prefix: %s\n",
1080 ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf,
1081 sizeof(buf), 0));
1082
1083 return 0;
1084 }
1085
1086 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1087 char *buf, int buflen,
1088 int pos)
1089 {
1090 struct ospf6_inter_router_lsa *router_lsa;
1091
1092 if (lsa != NULL) {
1093 router_lsa =
1094 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1095 lsa->header);
1096
1097
1098 if (buf)
1099 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1100 }
1101
1102 return (buf);
1103 }
1104
1105 static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1106 struct ospf6_lsa *lsa)
1107 {
1108 struct ospf6_inter_router_lsa *router_lsa;
1109 char buf[64];
1110
1111 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1112 lsa->header);
1113
1114 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1115 vty_out(vty, " Options: %s\n", buf);
1116 vty_out(vty, " Metric: %lu\n",
1117 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1118
1119 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1120 vty_out(vty, " Destination Router ID: %s\n", buf);
1121
1122 return 0;
1123 }
1124
1125 /* Debug commands */
1126 DEFUN (debug_ospf6_abr,
1127 debug_ospf6_abr_cmd,
1128 "debug ospf6 abr",
1129 DEBUG_STR
1130 OSPF6_STR
1131 "Debug OSPFv3 ABR function\n"
1132 )
1133 {
1134 OSPF6_DEBUG_ABR_ON();
1135 return CMD_SUCCESS;
1136 }
1137
1138 DEFUN (no_debug_ospf6_abr,
1139 no_debug_ospf6_abr_cmd,
1140 "no debug ospf6 abr",
1141 NO_STR
1142 DEBUG_STR
1143 OSPF6_STR
1144 "Debug OSPFv3 ABR function\n"
1145 )
1146 {
1147 OSPF6_DEBUG_ABR_OFF();
1148 return CMD_SUCCESS;
1149 }
1150
1151 int config_write_ospf6_debug_abr(struct vty *vty)
1152 {
1153 if (IS_OSPF6_DEBUG_ABR)
1154 vty_out(vty, "debug ospf6 abr\n");
1155 return 0;
1156 }
1157
1158 void install_element_ospf6_debug_abr(void)
1159 {
1160 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1161 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1162 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1163 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1164 }
1165
1166 struct ospf6_lsa_handler inter_prefix_handler = {
1167 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1168 .lh_name = "Inter-Prefix",
1169 .lh_short_name = "IAP",
1170 .lh_show = ospf6_inter_area_prefix_lsa_show,
1171 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
1172 .lh_debug = 0};
1173
1174 struct ospf6_lsa_handler inter_router_handler = {
1175 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1176 .lh_name = "Inter-Router",
1177 .lh_short_name = "IAR",
1178 .lh_show = ospf6_inter_area_router_lsa_show,
1179 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
1180 .lh_debug = 0};
1181
1182 void ospf6_abr_init(void)
1183 {
1184 ospf6_install_lsa_handler(&inter_prefix_handler);
1185 ospf6_install_lsa_handler(&inter_router_handler);
1186 }