]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_abr.c
ospf6d: ospf6_route_cmp_nexthops make return sane
[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_asbr.h"
50 #include "ospf6_abr.h"
51 #include "ospf6d.h"
52 #include "ospf6_nssa.h"
53
54 unsigned char conf_debug_ospf6_abr;
55
56 int ospf6_ls_origin_same(struct ospf6_path *o_path, struct ospf6_path *r_path)
57 {
58 if (((o_path->origin.type == r_path->origin.type)
59 && (o_path->origin.id == r_path->origin.id)
60 && (o_path->origin.adv_router == r_path->origin.adv_router)))
61 return 1;
62 else
63 return 0;
64 }
65
66 bool ospf6_check_and_set_router_abr(struct ospf6 *o)
67 {
68 struct listnode *node;
69 struct ospf6_area *oa;
70 int area_count = 0;
71 bool is_backbone = false;
72
73 for (ALL_LIST_ELEMENTS_RO(o->area_list, node, oa)) {
74 if (IS_OSPF6_DEBUG_ABR)
75 zlog_debug("%s, area_id %pI4", __func__, &oa->area_id);
76 if (IS_AREA_ENABLED(oa))
77 area_count++;
78
79 if (o->backbone == oa)
80 is_backbone = true;
81 }
82
83 if ((area_count > 1) && (is_backbone)) {
84 if (IS_OSPF6_DEBUG_ABR)
85 zlog_debug("%s : set flag OSPF6_FLAG_ABR", __func__);
86 SET_FLAG(o->flag, OSPF6_FLAG_ABR);
87 return true;
88 } else {
89 if (IS_OSPF6_DEBUG_ABR)
90 zlog_debug("%s : reset flag OSPF6_FLAG_ABR", __func__);
91 UNSET_FLAG(o->flag, OSPF6_FLAG_ABR);
92 return false;
93 }
94 }
95
96 static int ospf6_abr_nexthops_belong_to_area(struct ospf6_route *route,
97 struct ospf6_area *area)
98 {
99 struct ospf6_interface *oi;
100
101 oi = ospf6_interface_lookup_by_ifindex(
102 ospf6_route_get_first_nh_index(route), area->ospf6->vrf_id);
103 if (oi && oi->area && oi->area == area)
104 return 1;
105 else
106 return 0;
107 }
108
109 static void ospf6_abr_delete_route(struct ospf6_route *summary,
110 struct ospf6_route_table *summary_table,
111 struct ospf6_lsa *old)
112 {
113 if (summary) {
114 ospf6_route_remove(summary, summary_table);
115 }
116
117 if (old && !OSPF6_LSA_IS_MAXAGE(old))
118 ospf6_lsa_purge(old);
119 }
120
121 void ospf6_abr_enable_area(struct ospf6_area *area)
122 {
123 struct ospf6_area *oa;
124 struct listnode *node, *nnode;
125
126 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
127 /* update B bit for each area */
128 OSPF6_ROUTER_LSA_SCHEDULE(oa);
129 }
130
131 void ospf6_abr_disable_area(struct ospf6_area *area)
132 {
133 struct ospf6_area *oa;
134 struct ospf6_route *ro, *nro;
135 struct ospf6_lsa *old;
136 struct listnode *node, *nnode;
137
138 /* Withdraw all summary prefixes previously originated */
139 for (ro = ospf6_route_head(area->summary_prefix); ro; ro = nro) {
140 nro = ospf6_route_next(ro);
141 old = ospf6_lsdb_lookup(ro->path.origin.type,
142 ro->path.origin.id,
143 area->ospf6->router_id, area->lsdb);
144 if (old)
145 ospf6_lsa_purge(old);
146 ospf6_route_remove(ro, area->summary_prefix);
147 }
148
149 /* Withdraw all summary router-routes previously originated */
150 for (ro = ospf6_route_head(area->summary_router); ro; ro = nro) {
151 nro = ospf6_route_next(ro);
152 old = ospf6_lsdb_lookup(ro->path.origin.type,
153 ro->path.origin.id,
154 area->ospf6->router_id, area->lsdb);
155 if (old)
156 ospf6_lsa_purge(old);
157 ospf6_route_remove(ro, area->summary_router);
158 }
159
160 /* Schedule Router-LSA for each area (ABR status may change) */
161 for (ALL_LIST_ELEMENTS(area->ospf6->area_list, node, nnode, oa))
162 /* update B bit for each area */
163 OSPF6_ROUTER_LSA_SCHEDULE(oa);
164 }
165
166 /* RFC 2328 12.4.3. Summary-LSAs */
167 /* Returns 1 if a summary LSA has been generated for the area */
168 /* This is used by the area/range logic to add/remove blackhole routes */
169 int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
170 struct ospf6_area *area)
171 {
172 struct ospf6_lsa *lsa, *old = NULL;
173 struct ospf6_route *summary, *range = NULL;
174 struct ospf6_area *route_area;
175 char buffer[OSPF6_MAX_LSASIZE];
176 struct ospf6_lsa_header *lsa_header;
177 caddr_t p;
178 struct ospf6_inter_prefix_lsa *prefix_lsa;
179 struct ospf6_inter_router_lsa *router_lsa;
180 struct ospf6_route_table *summary_table = NULL;
181 uint16_t type;
182 int is_debug = 0;
183
184 if (IS_OSPF6_DEBUG_ABR) {
185 char buf[BUFSIZ];
186
187 if (route->type == OSPF6_DEST_TYPE_ROUTER)
188 inet_ntop(AF_INET,
189 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
190 sizeof(buf));
191 else
192 prefix2str(&route->prefix, buf, sizeof(buf));
193
194 zlog_debug("%s : start area %s, route %s", __func__, area->name,
195 buf);
196 }
197
198 if (route->type == OSPF6_DEST_TYPE_ROUTER)
199 summary_table = area->summary_router;
200 else
201 summary_table = area->summary_prefix;
202
203 summary = ospf6_route_lookup(&route->prefix, summary_table);
204 if (summary) {
205 old = ospf6_lsdb_lookup(summary->path.origin.type,
206 summary->path.origin.id,
207 area->ospf6->router_id, area->lsdb);
208 /* Reset the OSPF6_LSA_UNAPPROVED flag */
209 if (old)
210 UNSET_FLAG(old->flag, OSPF6_LSA_UNAPPROVED);
211 }
212
213 /* Only destination type network, range or ASBR are considered */
214 if (route->type != OSPF6_DEST_TYPE_NETWORK
215 && route->type != OSPF6_DEST_TYPE_RANGE
216 && ((route->type != OSPF6_DEST_TYPE_ROUTER)
217 || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) {
218 if (IS_OSPF6_DEBUG_ABR)
219 zlog_debug(
220 "%s: Route type %d flag 0x%x is none of network, range nor ASBR, ignore",
221 __func__, route->type, route->path.router_bits);
222 return 0;
223 }
224
225 /* AS External routes are never considered */
226 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
227 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) {
228 if (IS_OSPF6_DEBUG_ABR)
229 zlog_debug("%s : Path type is external, skip",
230 __func__);
231 return 0;
232 }
233
234 /* do not generate if the path's area is the same as target area */
235 if (route->path.area_id == area->area_id) {
236 if (IS_OSPF6_DEBUG_ABR)
237 zlog_debug(
238 "%s: The route is in the area itself, ignore",
239 __func__);
240 return 0;
241 }
242
243 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
244 bool filter = false;
245
246 route_area =
247 ospf6_area_lookup(route->path.area_id, area->ospf6);
248 assert(route_area);
249
250 /* Check export-list */
251 if (EXPORT_LIST(route_area)
252 && access_list_apply(EXPORT_LIST(route_area),
253 &route->prefix)
254 == FILTER_DENY) {
255 if (IS_OSPF6_DEBUG_ABR)
256 zlog_debug(
257 "%s: prefix %pFX was denied by export-list",
258 __func__, &route->prefix);
259 filter = true;
260 }
261
262 /* Check output prefix-list */
263 if (PREFIX_LIST_OUT(route_area)
264 && prefix_list_apply(PREFIX_LIST_OUT(route_area),
265 &route->prefix)
266 != PREFIX_PERMIT) {
267 if (IS_OSPF6_DEBUG_ABR)
268 zlog_debug(
269 "%s: prefix %pFX was denied by prefix-list out",
270 __func__, &route->prefix);
271 filter = true;
272 }
273
274 /* Check import-list */
275 if (IMPORT_LIST(area)
276 && access_list_apply(IMPORT_LIST(area), &route->prefix)
277 == FILTER_DENY) {
278 if (IS_OSPF6_DEBUG_ABR)
279 zlog_debug(
280 "%s: prefix %pFX was denied by import-list",
281 __func__, &route->prefix);
282 filter = true;
283 }
284
285 /* Check input prefix-list */
286 if (PREFIX_LIST_IN(area)
287 && prefix_list_apply(PREFIX_LIST_IN(area), &route->prefix)
288 != PREFIX_PERMIT) {
289 if (IS_OSPF6_DEBUG_ABR)
290 zlog_debug(
291 "%s: prefix %pFX was denied by prefix-list in",
292 __func__, &route->prefix);
293 filter = true;
294 }
295
296 if (filter) {
297 if (summary) {
298 ospf6_route_remove(summary, summary_table);
299 if (old)
300 ospf6_lsa_purge(old);
301 }
302 return 0;
303 }
304 }
305
306 /* do not generate if the nexthops belongs to the target area */
307 if (ospf6_abr_nexthops_belong_to_area(route, area)) {
308 if (IS_OSPF6_DEBUG_ABR)
309 zlog_debug(
310 "%s: The route's nexthop is in the same area, ignore",
311 __func__);
312 return 0;
313 }
314
315 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
316 if (ADV_ROUTER_IN_PREFIX(&route->prefix)
317 == area->ospf6->router_id) {
318 if (IS_OSPF6_DEBUG_ABR)
319 zlog_debug(
320 "%s: Skipping ASBR announcement for ABR (%pI4)",
321 __func__,
322 &ADV_ROUTER_IN_PREFIX(&route->prefix));
323 return 0;
324 }
325 }
326
327 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
328 if (IS_OSPF6_DEBUG_ABR
329 || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) {
330 is_debug++;
331 if (IS_OSPF6_DEBUG_ABR)
332 zlog_debug(
333 "Originating summary in area %s for ASBR %pI4",
334 area->name,
335 &ADV_ROUTER_IN_PREFIX(&route->prefix));
336 }
337 } else {
338 if (IS_OSPF6_DEBUG_ABR
339 || IS_OSPF6_DEBUG_ORIGINATE(INTER_PREFIX))
340 is_debug++;
341
342 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
343 route->path.origin.type ==
344 htons(OSPF6_LSTYPE_INTER_PREFIX)) {
345 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
346 if (is_debug)
347 zlog_debug(
348 "%s: route %pFX with cost %u is not best, ignore.",
349 __func__, &route->prefix,
350 route->path.cost);
351 return 0;
352 }
353 }
354
355 if (route->path.origin.type ==
356 htons(OSPF6_LSTYPE_INTRA_PREFIX)) {
357 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
358 if (is_debug)
359 zlog_debug(
360 "%s: intra-prefix route %pFX with cost %u is not best, ignore.",
361 __func__, &route->prefix,
362 route->path.cost);
363 return 0;
364 }
365 }
366
367 if (is_debug)
368 zlog_debug(
369 "Originating summary in area %s for %pFX cost %u",
370 area->name, &route->prefix, route->path.cost);
371 }
372
373 /* if this route has just removed, remove corresponding LSA */
374 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)) {
375 if (is_debug)
376 zlog_debug(
377 "The route has just removed, purge previous LSA");
378
379 if (route->type == OSPF6_DEST_TYPE_RANGE) {
380 /* Whether the route have active longer prefix */
381 if (!CHECK_FLAG(route->flag,
382 OSPF6_ROUTE_ACTIVE_SUMMARY)) {
383 if (is_debug)
384 zlog_debug(
385 "The range is not active. withdraw");
386
387 ospf6_abr_delete_route(summary, summary_table,
388 old);
389 }
390 } else if (old) {
391 ospf6_route_remove(summary, summary_table);
392 ospf6_lsa_purge(old);
393 }
394 return 0;
395 }
396
397 if ((route->type == OSPF6_DEST_TYPE_ROUTER)
398 && (IS_AREA_STUB(area) || IS_AREA_NSSA(area))) {
399 if (is_debug)
400 zlog_debug(
401 "Area has been stubbed, purge Inter-Router LSA");
402
403 ospf6_abr_delete_route(summary, summary_table, old);
404 return 0;
405 }
406
407 if (area->no_summary
408 && (route->path.subtype != OSPF6_PATH_SUBTYPE_DEFAULT_RT)) {
409 if (is_debug)
410 zlog_debug("Area has been stubbed, purge prefix LSA");
411
412 ospf6_abr_delete_route(summary, summary_table, old);
413 return 0;
414 }
415
416 /* do not generate if the route cost is greater or equal to LSInfinity
417 */
418 if (route->path.cost >= OSPF_LS_INFINITY) {
419 /* When we're clearing the range route because all active
420 * prefixes
421 * under the range are gone, we set the range's cost to
422 * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We
423 * don't want to trigger the code here for that. This code is
424 * for
425 * handling routes that have gone to infinity. The range removal
426 * happens
427 * elsewhere.
428 */
429 if ((route->type != OSPF6_DEST_TYPE_RANGE)
430 && (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) {
431 if (is_debug)
432 zlog_debug(
433 "The cost exceeds LSInfinity, withdraw");
434 if (old)
435 ospf6_lsa_purge(old);
436 return 0;
437 }
438 }
439
440 /* if this is a route to ASBR */
441 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
442 /* Only the preferred best path is considered */
443 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) {
444 if (is_debug)
445 zlog_debug(
446 "This is the secondary path to the ASBR, ignore");
447 ospf6_abr_delete_route(summary, summary_table, old);
448 return 0;
449 }
450
451 /* Do not generate if area is NSSA */
452 route_area =
453 ospf6_area_lookup(route->path.area_id, area->ospf6);
454 assert(route_area);
455
456 if (IS_AREA_NSSA(route_area)) {
457 if (is_debug)
458 zlog_debug(
459 "%s: The route comes from NSSA area, skip",
460 __func__);
461 ospf6_abr_delete_route(summary, summary_table, old);
462 return 0;
463 }
464
465 /* Do not generate if the area is stub */
466 /* XXX */
467 }
468
469 /* if this is an intra-area route, this may be suppressed by aggregation
470 */
471 if (route->type == OSPF6_DEST_TYPE_NETWORK
472 && route->path.type == OSPF6_PATH_TYPE_INTRA) {
473 /* search for configured address range for the route's area */
474 route_area =
475 ospf6_area_lookup(route->path.area_id, area->ospf6);
476 assert(route_area);
477 range = ospf6_route_lookup_bestmatch(&route->prefix,
478 route_area->range_table);
479
480 /* ranges are ignored when originate backbone routes to transit
481 area.
482 Otherwise, if ranges are configured, the route is suppressed.
483 */
484 if (range && !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)
485 && (route->path.area_id != OSPF_AREA_BACKBONE
486 || !IS_AREA_TRANSIT(area))) {
487 if (is_debug)
488 zlog_debug(
489 "Suppressed by range %pFX of area %s",
490 &range->prefix, route_area->name);
491 /* The existing summary route could be a range, don't
492 * remove it in this case
493 */
494 if (summary && summary->type != OSPF6_DEST_TYPE_RANGE)
495 ospf6_abr_delete_route(summary, summary_table,
496 old);
497 return 0;
498 }
499 }
500
501 /* If this is a configured address range */
502 if (route->type == OSPF6_DEST_TYPE_RANGE) {
503 /* If DoNotAdvertise is set */
504 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
505 if (is_debug)
506 zlog_debug(
507 "This is the range with DoNotAdvertise set. ignore");
508 ospf6_abr_delete_route(summary, summary_table, old);
509 return 0;
510 }
511
512 /* If there are no active prefixes in this range, remove */
513 if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
514 if (is_debug)
515 zlog_debug("The range is not active. withdraw");
516 ospf6_abr_delete_route(summary, summary_table, old);
517 return 0;
518 }
519 }
520
521 /* the route is going to be originated. store it in area's summary_table
522 */
523 if (summary == NULL) {
524 summary = ospf6_route_copy(route);
525 summary->path.origin.adv_router = area->ospf6->router_id;
526
527 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
528 summary->path.origin.type =
529 htons(OSPF6_LSTYPE_INTER_ROUTER);
530 summary->path.origin.id =
531 ADV_ROUTER_IN_PREFIX(&route->prefix);
532 } else {
533 summary->path.origin.type =
534 htons(OSPF6_LSTYPE_INTER_PREFIX);
535 summary->path.origin.id = ospf6_new_ls_id(
536 summary->path.origin.type,
537 summary->path.origin.adv_router, area->lsdb);
538 }
539 summary = ospf6_route_add(summary, summary_table);
540 } else {
541 summary->type = route->type;
542 monotime(&summary->changed);
543 }
544
545 summary->prefix_options = route->prefix_options;
546 summary->path.router_bits = route->path.router_bits;
547 summary->path.options[0] = route->path.options[0];
548 summary->path.options[1] = route->path.options[1];
549 summary->path.options[2] = route->path.options[2];
550 summary->path.area_id = area->area_id;
551 summary->path.type = OSPF6_PATH_TYPE_INTER;
552 summary->path.subtype = route->path.subtype;
553 summary->path.cost = route->path.cost;
554 /* summary->nexthop[0] = route->nexthop[0]; */
555
556 /* prepare buffer */
557 memset(buffer, 0, sizeof(buffer));
558 lsa_header = (struct ospf6_lsa_header *)buffer;
559
560 if (route->type == OSPF6_DEST_TYPE_ROUTER) {
561 router_lsa = (struct ospf6_inter_router_lsa
562 *)((caddr_t)lsa_header
563 + sizeof(struct ospf6_lsa_header));
564 p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
565
566 /* Fill Inter-Area-Router-LSA */
567 router_lsa->options[0] = route->path.options[0];
568 router_lsa->options[1] = route->path.options[1];
569 router_lsa->options[2] = route->path.options[2];
570 OSPF6_ABR_SUMMARY_METRIC_SET(router_lsa, route->path.cost);
571 router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
572 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
573 } else {
574 prefix_lsa = (struct ospf6_inter_prefix_lsa
575 *)((caddr_t)lsa_header
576 + sizeof(struct ospf6_lsa_header));
577 p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
578
579 /* Fill Inter-Area-Prefix-LSA */
580 OSPF6_ABR_SUMMARY_METRIC_SET(prefix_lsa, route->path.cost);
581 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
582 prefix_lsa->prefix.prefix_options = route->prefix_options;
583
584 /* set Prefix */
585 memcpy(p, &route->prefix.u.prefix6,
586 OSPF6_PREFIX_SPACE(route->prefix.prefixlen));
587 ospf6_prefix_apply_mask(&prefix_lsa->prefix);
588 p += OSPF6_PREFIX_SPACE(route->prefix.prefixlen);
589 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
590 }
591
592 /* Fill LSA Header */
593 lsa_header->age = 0;
594 lsa_header->type = type;
595 lsa_header->id = summary->path.origin.id;
596 lsa_header->adv_router = area->ospf6->router_id;
597 lsa_header->seqnum =
598 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
599 lsa_header->adv_router, area->lsdb);
600 lsa_header->length = htons((caddr_t)p - (caddr_t)lsa_header);
601
602 /* LSA checksum */
603 ospf6_lsa_checksum(lsa_header);
604
605 /* create LSA */
606 lsa = ospf6_lsa_create(lsa_header);
607
608 /* Reset the unapproved flag */
609 UNSET_FLAG(lsa->flag, OSPF6_LSA_UNAPPROVED);
610
611 /* Originate */
612 ospf6_lsa_originate_area(lsa, area);
613
614 if (IS_OSPF6_DEBUG_ABR)
615 zlog_debug("%s : finish area %s", __func__, area->name);
616
617 return 1;
618 }
619
620 void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
621 {
622 struct listnode *node, *nnode;
623 struct ospf6_area *oa;
624 struct ospf6_route *range;
625
626 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
627 for (range = ospf6_route_head(oa->range_table); range;
628 range = ospf6_route_next(range))
629 OSPF6_ABR_RANGE_CLEAR_COST(range);
630 for (range = ospf6_route_head(oa->nssa_range_table); range;
631 range = ospf6_route_next(range))
632 OSPF6_ABR_RANGE_CLEAR_COST(range);
633 }
634 }
635
636 static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
637 struct ospf6 *o)
638 {
639 struct ospf6_route *ro;
640 uint32_t cost = 0;
641
642 for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
643 ro = ospf6_route_match_next(&range->prefix, ro)) {
644 if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
645 continue;
646 if (ro->path.area_id != range->path.area_id)
647 continue;
648 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
649 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
650 && ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
651 continue;
652 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
653 && ro->path.type != OSPF6_PATH_TYPE_INTRA)
654 continue;
655
656 cost = MAX(cost, ro->path.cost);
657 }
658
659 return cost;
660 }
661
662 static inline int
663 ospf6_abr_range_summary_needs_update(struct ospf6_route *range, uint32_t cost)
664 {
665 int redo_summary = 0;
666
667 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
668 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
669 redo_summary = 1;
670 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
671 if (range->path.cost != 0) {
672 range->path.cost = 0;
673 redo_summary = 1;
674 }
675 } else if (cost) {
676 if ((OSPF6_PATH_COST_IS_CONFIGURED(range->path)
677 && range->path.cost != range->path.u.cost_config)) {
678 range->path.cost = range->path.u.cost_config;
679 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
680 redo_summary = 1;
681 } else if (!OSPF6_PATH_COST_IS_CONFIGURED(range->path)
682 && range->path.cost != cost) {
683 range->path.cost = cost;
684 SET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
685 redo_summary = 1;
686 }
687 } else if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) {
688 /* Cost is zero, meaning no active range */
689 UNSET_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
690 range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
691 redo_summary = 1;
692 }
693
694 return (redo_summary);
695 }
696
697 void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
698 {
699 uint32_t cost = 0;
700 struct listnode *node, *nnode;
701 struct ospf6_area *oa;
702 int summary_orig = 0;
703
704 assert(range->type == OSPF6_DEST_TYPE_RANGE);
705 oa = ospf6_area_lookup(range->path.area_id, ospf6);
706 assert(oa);
707
708 /* update range's cost and active flag */
709 cost = ospf6_abr_range_compute_cost(range, ospf6);
710
711 if (IS_OSPF6_DEBUG_ABR)
712 zlog_debug("%s: range %pFX, cost %d", __func__, &range->prefix,
713 cost);
714
715 /* Non-zero cost is a proxy for active longer prefixes in this range.
716 * If there are active routes covered by this range AND either the
717 * configured
718 * cost has changed or the summarized cost has changed then redo
719 * summaries.
720 * Alternately, if there are no longer active prefixes and there are
721 * summary announcements, withdraw those announcements.
722 *
723 * The don't advertise code relies on the path.cost being set to UNSPEC
724 * to
725 * work the first time. Subsequent times the path.cost is not 0 anyway
726 * if there
727 * were active ranges.
728 */
729 if (!ospf6_abr_range_summary_needs_update(range, cost))
730 return;
731
732 if (IS_OSPF6_DEBUG_ABR)
733 zlog_debug("%s: range %pFX update", __func__, &range->prefix);
734
735 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
736 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
737 && !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
738 ospf6_nssa_lsa_originate(range, oa, true);
739 summary_orig = 1;
740 } else {
741 struct ospf6_lsa *lsa;
742
743 lsa = ospf6_lsdb_lookup(range->path.origin.type,
744 range->path.origin.id,
745 ospf6->router_id, oa->lsdb);
746 if (lsa)
747 ospf6_lsa_premature_aging(lsa);
748 }
749 } else {
750 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
751 summary_orig +=
752 ospf6_abr_originate_summary_to_area(range, oa);
753 }
754 }
755
756 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
757 && summary_orig) {
758 if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
759 if (IS_OSPF6_DEBUG_ABR)
760 zlog_debug("Add discard route");
761
762 ospf6_zebra_add_discard(range, ospf6);
763 }
764 } else {
765 /* Summary removed or no summary generated as no
766 * specifics exist */
767 if (CHECK_FLAG(range->flag, OSPF6_ROUTE_BLACKHOLE_ADDED)) {
768 if (IS_OSPF6_DEBUG_ABR)
769 zlog_debug("Delete discard route");
770
771 ospf6_zebra_delete_discard(range, ospf6);
772 }
773 }
774 }
775
776 void ospf6_abr_originate_summary(struct ospf6_route *route, struct ospf6 *ospf6)
777 {
778 struct listnode *node, *nnode;
779 struct ospf6_area *oa;
780 struct ospf6_route *range = NULL;
781
782 if (IS_OSPF6_DEBUG_ABR) {
783 char buf[BUFSIZ];
784
785 if (route->type == OSPF6_DEST_TYPE_ROUTER)
786 inet_ntop(AF_INET,
787 &ADV_ROUTER_IN_PREFIX(&route->prefix), buf,
788 sizeof(buf));
789 else
790 prefix2str(&route->prefix, buf, sizeof(buf));
791
792 zlog_debug("%s: route %s", __func__, buf);
793 }
794
795 if (route->type == OSPF6_DEST_TYPE_NETWORK) {
796 oa = ospf6_area_lookup(route->path.area_id, ospf6);
797 if (!oa) {
798 zlog_err("OSPFv6 area lookup failed");
799 return;
800 }
801
802 range = ospf6_route_lookup_bestmatch(&route->prefix,
803 oa->range_table);
804 if (range) {
805 ospf6_abr_range_update(range, ospf6);
806 }
807 }
808
809 for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
810 ospf6_abr_originate_summary_to_area(route, oa);
811 }
812
813 void ospf6_abr_defaults_to_stub(struct ospf6 *o)
814 {
815 struct listnode *node, *nnode;
816 struct ospf6_area *oa;
817 struct ospf6_route *def, *route;
818 int type = DEFAULT_ROUTE;
819
820 if (!o->backbone)
821 return;
822
823 def = ospf6_route_create(o);
824 def->type = OSPF6_DEST_TYPE_NETWORK;
825 def->prefix.family = AF_INET6;
826 def->prefix.prefixlen = 0;
827 memset(&def->prefix.u.prefix6, 0, sizeof(struct in6_addr));
828 def->type = OSPF6_DEST_TYPE_NETWORK;
829 def->path.type = OSPF6_PATH_TYPE_INTER;
830 def->path.subtype = OSPF6_PATH_SUBTYPE_DEFAULT_RT;
831 def->path.area_id = o->backbone->area_id;
832 def->path.metric_type = metric_type(o, type, 0);
833 def->path.cost = metric_value(o, type, 0);
834
835 for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa)) {
836 if (IS_AREA_STUB(oa) || (IS_AREA_NSSA(oa) && oa->no_summary)) {
837 /* announce defaults to stubby areas */
838 if (IS_OSPF6_DEBUG_ABR)
839 zlog_debug(
840 "Announcing default route into stubby area %s",
841 oa->name);
842 UNSET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
843 ospf6_abr_originate_summary_to_area(def, oa);
844 } else {
845 /* withdraw defaults when an area switches from stub to
846 * non-stub */
847 route = ospf6_route_lookup(&def->prefix,
848 oa->summary_prefix);
849 if (route
850 && (route->path.subtype == def->path.subtype)) {
851 if (IS_OSPF6_DEBUG_ABR)
852 zlog_debug(
853 "Withdrawing default route from non-stubby area %s",
854 oa->name);
855 SET_FLAG(def->flag, OSPF6_ROUTE_REMOVE);
856 ospf6_abr_originate_summary_to_area(def, oa);
857 }
858 }
859 }
860 ospf6_route_delete(def);
861 }
862
863 void ospf6_abr_old_path_update(struct ospf6_route *old_route,
864 struct ospf6_route *route,
865 struct ospf6_route_table *table)
866 {
867 struct ospf6_path *o_path = NULL;
868 struct listnode *anode, *anext;
869 struct listnode *nnode, *rnode, *rnext;
870 struct ospf6_nexthop *nh, *rnh;
871
872 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext, o_path)) {
873 if (o_path->area_id != route->path.area_id
874 || !ospf6_ls_origin_same(o_path, &route->path))
875 continue;
876
877 if ((o_path->cost == route->path.cost) &&
878 (o_path->u.cost_e2 == route->path.u.cost_e2))
879 continue;
880
881 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
882 for (ALL_LIST_ELEMENTS(old_route->nh_list, rnode,
883 rnext, rnh)) {
884 if (!ospf6_nexthop_is_same(rnh, nh))
885 continue;
886 listnode_delete(old_route->nh_list, rnh);
887 ospf6_nexthop_delete(rnh);
888 }
889
890 }
891
892 listnode_delete(old_route->paths, o_path);
893 ospf6_path_free(o_path);
894
895 for (ALL_LIST_ELEMENTS(old_route->paths, anode,
896 anext, o_path)) {
897 ospf6_merge_nexthops(old_route->nh_list,
898 o_path->nh_list);
899 }
900
901 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
902 zlog_debug("%s: paths %u nh %u", __func__,
903 old_route->paths
904 ? listcount(old_route->paths)
905 : 0,
906 old_route->nh_list
907 ? listcount(old_route->nh_list)
908 : 0);
909
910 if (table->hook_add)
911 (*table->hook_add)(old_route);
912
913 if (old_route->path.origin.id == route->path.origin.id &&
914 old_route->path.origin.adv_router ==
915 route->path.origin.adv_router) {
916 struct ospf6_path *h_path;
917
918 h_path = (struct ospf6_path *)
919 listgetdata(listhead(old_route->paths));
920 old_route->path.origin.type = h_path->origin.type;
921 old_route->path.origin.id = h_path->origin.id;
922 old_route->path.origin.adv_router =
923 h_path->origin.adv_router;
924 }
925 }
926 }
927
928 void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old,
929 struct ospf6_route_table *table)
930 {
931 if (IS_OSPF6_DEBUG_ABR)
932 zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix,
933 listcount(old->paths));
934
935 if (listcount(old->paths) > 1) {
936 struct listnode *anode, *anext, *nnode, *rnode, *rnext;
937 struct ospf6_path *o_path;
938 struct ospf6_nexthop *nh, *rnh;
939 bool nh_updated = false;
940
941 for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) {
942 if (o_path->origin.adv_router != lsa->header->adv_router
943 || o_path->origin.id != lsa->header->id)
944 continue;
945 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
946 for (ALL_LIST_ELEMENTS(old->nh_list,
947 rnode, rnext, rnh)) {
948 if (!ospf6_nexthop_is_same(rnh, nh))
949 continue;
950 if (IS_OSPF6_DEBUG_ABR)
951 zlog_debug("deleted nexthop");
952 listnode_delete(old->nh_list, rnh);
953 ospf6_nexthop_delete(rnh);
954 }
955 }
956 listnode_delete(old->paths, o_path);
957 ospf6_path_free(o_path);
958 nh_updated = true;
959 }
960
961 if (nh_updated) {
962 if (listcount(old->paths)) {
963 if (IS_OSPF6_DEBUG_ABR
964 || IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX))
965 zlog_debug("%s: old %pFX updated nh %u",
966 __func__, &old->prefix,
967 old->nh_list ? listcount(
968 old->nh_list)
969 : 0);
970
971 if (table->hook_add)
972 (*table->hook_add)(old);
973
974 if ((old->path.origin.id == lsa->header->id) &&
975 (old->path.origin.adv_router
976 == lsa->header->adv_router)) {
977 struct ospf6_path *h_path;
978
979 h_path = (struct ospf6_path *)
980 listgetdata(
981 listhead(old->paths));
982 old->path.origin.type =
983 h_path->origin.type;
984 old->path.origin.id = h_path->origin.id;
985 old->path.origin.adv_router =
986 h_path->origin.adv_router;
987 }
988 } else
989 ospf6_route_remove(old, table);
990 }
991 } else
992 ospf6_route_remove(old, table);
993 }
994
995 /* RFC 2328 16.2. Calculating the inter-area routes */
996 void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
997 {
998 struct prefix prefix, abr_prefix;
999 struct ospf6_route_table *table = NULL;
1000 struct ospf6_route *range, *route, *old = NULL, *old_route;
1001 struct ospf6_route *abr_entry;
1002 uint8_t type = 0;
1003 char options[3] = {0, 0, 0};
1004 uint8_t prefix_options = 0;
1005 uint32_t cost = 0;
1006 uint8_t router_bits = 0;
1007 char buf[PREFIX2STR_BUFFER];
1008 int is_debug = 0;
1009 struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
1010 struct ospf6_inter_router_lsa *router_lsa = NULL;
1011 bool old_entry_updated = false;
1012 struct ospf6_path *path, *o_path, *ecmp_path;
1013 struct listnode *anode;
1014 bool add_route = false;
1015
1016 memset(&prefix, 0, sizeof(prefix));
1017
1018 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1019 if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) {
1020 is_debug++;
1021 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1022 lsa->name, ospf6_lsa_age_current(lsa),
1023 oa->name);
1024 }
1025
1026 prefix_lsa =
1027 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1028 lsa->header);
1029 prefix.family = AF_INET6;
1030 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
1031 ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
1032 &prefix_lsa->prefix);
1033 if (is_debug)
1034 prefix2str(&prefix, buf, sizeof(buf));
1035 table = oa->ospf6->route_table;
1036 type = OSPF6_DEST_TYPE_NETWORK;
1037 prefix_options = prefix_lsa->prefix.prefix_options;
1038 cost = OSPF6_ABR_SUMMARY_METRIC(prefix_lsa);
1039 } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1040 if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) {
1041 is_debug++;
1042 zlog_debug("%s: LSA %s age %d in area %s", __func__,
1043 lsa->name, ospf6_lsa_age_current(lsa),
1044 oa->name);
1045 }
1046
1047 router_lsa =
1048 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1049 lsa->header);
1050 ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
1051 &prefix);
1052 if (is_debug)
1053 inet_ntop(AF_INET, &router_lsa->router_id, buf,
1054 sizeof(buf));
1055
1056 table = oa->ospf6->brouter_table;
1057 type = OSPF6_DEST_TYPE_ROUTER;
1058 options[0] = router_lsa->options[0];
1059 options[1] = router_lsa->options[1];
1060 options[2] = router_lsa->options[2];
1061 cost = OSPF6_ABR_SUMMARY_METRIC(router_lsa);
1062 SET_FLAG(router_bits, OSPF6_ROUTER_BIT_E);
1063 } else
1064 assert(0);
1065
1066 /* Find existing route */
1067 route = ospf6_route_lookup(&prefix, table);
1068 if (route) {
1069 ospf6_route_lock(route);
1070 if (is_debug)
1071 zlog_debug("%s: route %pFX, paths %d", __func__,
1072 &prefix, listcount(route->paths));
1073 }
1074 while (route && ospf6_route_is_prefix(&prefix, route)) {
1075 if (route->path.area_id == oa->area_id
1076 && route->path.origin.type == lsa->header->type
1077 && !CHECK_FLAG(route->flag, OSPF6_ROUTE_WAS_REMOVED)) {
1078 /* LSA adv. router could be part of route's
1079 * paths list. Find the existing path and set
1080 * old as the route.
1081 */
1082 if (listcount(route->paths) > 1) {
1083 for (ALL_LIST_ELEMENTS_RO(route->paths, anode,
1084 o_path)) {
1085 if (o_path->origin.id == lsa->header->id
1086 && o_path->origin.adv_router ==
1087 lsa->header->adv_router) {
1088 old = route;
1089
1090 if (is_debug)
1091 zlog_debug(
1092 "%s: old entry found in paths, adv_router %pI4",
1093 __func__,
1094 &o_path->origin.adv_router);
1095
1096 break;
1097 }
1098 }
1099 } else if (route->path.origin.id == lsa->header->id &&
1100 route->path.origin.adv_router ==
1101 lsa->header->adv_router)
1102 old = route;
1103 }
1104 route = ospf6_route_next(route);
1105 }
1106 if (route)
1107 ospf6_route_unlock(route);
1108
1109 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
1110 if (cost == OSPF_LS_INFINITY) {
1111 if (is_debug)
1112 zlog_debug("cost is LS_INFINITY, ignore");
1113 if (old)
1114 ospf6_abr_old_route_remove(lsa, old, table);
1115 return;
1116 }
1117 if (OSPF6_LSA_IS_MAXAGE(lsa)) {
1118 if (is_debug)
1119 zlog_debug("%s: LSA %s is MaxAge, ignore", __func__,
1120 lsa->name);
1121 if (old)
1122 ospf6_abr_old_route_remove(lsa, old, table);
1123 return;
1124 }
1125
1126
1127 /* (2) if the LSA is self-originated, ignore */
1128 if (lsa->header->adv_router == oa->ospf6->router_id) {
1129 if (is_debug)
1130 zlog_debug("LSA %s is self-originated, ignore",
1131 lsa->name);
1132 if (old)
1133 ospf6_route_remove(old, table);
1134 return;
1135 }
1136
1137 /* (3) if the prefix is equal to an active configured address range */
1138 /* or if the NU bit is set in the prefix */
1139 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) {
1140 /* must have been set in previous block */
1141 assert(prefix_lsa);
1142
1143 range = ospf6_route_lookup(&prefix, oa->range_table);
1144 if (range) {
1145 if (is_debug)
1146 zlog_debug(
1147 "Prefix is equal to address range, ignore");
1148 if (old)
1149 ospf6_route_remove(old, table);
1150 return;
1151 }
1152
1153 if (CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1154 OSPF6_PREFIX_OPTION_NU)
1155 || CHECK_FLAG(prefix_lsa->prefix.prefix_options,
1156 OSPF6_PREFIX_OPTION_LA)) {
1157 if (is_debug)
1158 zlog_debug("Prefix has NU/LA bit set, ignore");
1159 if (old)
1160 ospf6_route_remove(old, table);
1161 return;
1162 }
1163 }
1164
1165 if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) {
1166 /* To pass test suites */
1167 assert(router_lsa);
1168 if (!OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_R)
1169 || !OSPF6_OPT_ISSET(router_lsa->options, OSPF6_OPT_V6)) {
1170 if (is_debug)
1171 zlog_debug("Prefix has NU/LA bit set, ignore");
1172 if (old)
1173 ospf6_route_remove(old, table);
1174
1175 return;
1176 }
1177 /* Avoid infinite recursion if someone has maliciously announced
1178 an
1179 Inter-Router LSA for an ABR
1180 */
1181 if (lsa->header->adv_router == router_lsa->router_id) {
1182 if (is_debug)
1183 zlog_debug(
1184 "Ignoring Inter-Router LSA for an ABR (%s)",
1185 buf);
1186 if (old)
1187 ospf6_route_remove(old, table);
1188
1189 return;
1190 }
1191 }
1192
1193 /* (4) if the routing table entry for the ABR does not exist */
1194 ospf6_linkstate_prefix(lsa->header->adv_router, htonl(0), &abr_prefix);
1195 abr_entry = ospf6_route_lookup(&abr_prefix, oa->ospf6->brouter_table);
1196 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id
1197 || CHECK_FLAG(abr_entry->flag, OSPF6_ROUTE_REMOVE)
1198 || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) {
1199 if (is_debug)
1200 zlog_debug(
1201 "%s: ABR router entry %pFX does not exist, ignore",
1202 __func__, &abr_prefix);
1203 if (old) {
1204 if (old->type == OSPF6_DEST_TYPE_ROUTER &&
1205 oa->intra_brouter_calc) {
1206 if (is_debug)
1207 zlog_debug(
1208 "%s: intra_brouter_calc is on, skip brouter remove: %s (%p)",
1209 __func__, buf, (void *)old);
1210 } else {
1211 if (is_debug)
1212 zlog_debug(
1213 "%s: remove old entry: %s %p ",
1214 __func__, buf, (void *)old);
1215 ospf6_abr_old_route_remove(lsa, old, table);
1216 }
1217 }
1218 return;
1219 }
1220
1221 /* (5),(6): the path preference is handled by the sorting
1222 in the routing table. Always install the path by substituting
1223 old route (if any). */
1224 route = ospf6_route_create(oa->ospf6);
1225
1226 route->type = type;
1227 route->prefix = prefix;
1228 route->prefix_options = prefix_options;
1229 route->path.origin.type = lsa->header->type;
1230 route->path.origin.id = lsa->header->id;
1231 route->path.origin.adv_router = lsa->header->adv_router;
1232 route->path.router_bits = router_bits;
1233 route->path.options[0] = options[0];
1234 route->path.options[1] = options[1];
1235 route->path.options[2] = options[2];
1236 route->path.area_id = oa->area_id;
1237 route->path.type = OSPF6_PATH_TYPE_INTER;
1238 route->path.cost = abr_entry->path.cost + cost;
1239
1240 /* copy brouter rechable nexthops into the route. */
1241 ospf6_route_copy_nexthops(route, abr_entry);
1242
1243 /* (7) If the routes are identical, copy the next hops over to existing
1244 route. ospf6's route table implementation will otherwise string both
1245 routes, but keep the older one as the best route since the routes
1246 are identical.
1247 */
1248 old = ospf6_route_lookup(&prefix, table);
1249 if (old) {
1250 if (is_debug)
1251 zlog_debug("%s: found old route %pFX, paths %d",
1252 __func__, &prefix, listcount(old->paths));
1253 }
1254 for (old_route = old; old_route; old_route = old_route->next) {
1255
1256 /* The route linked-list is grouped in batches of prefix.
1257 * If the new prefix is not the same as the one of interest
1258 * then we have walked over the end of the batch and so we
1259 * should break rather than continuing unnecessarily.
1260 */
1261 if (!ospf6_route_is_same(old_route, route))
1262 break;
1263 if ((old_route->type != route->type)
1264 || (old_route->path.type != route->path.type))
1265 continue;
1266
1267 if ((ospf6_route_cmp(route, old_route) != 0)) {
1268 if (is_debug)
1269 zlog_debug(
1270 "%s: old %p %pFX cost %u new route cost %u are not same",
1271 __func__, (void *)old_route, &prefix,
1272 old_route->path.cost, route->path.cost);
1273
1274 /* Check new route's adv. router is same in one of
1275 * the paths with differed cost, if so remove the
1276 * old path as later new route will be added.
1277 */
1278 if (listcount(old_route->paths) > 1)
1279 ospf6_abr_old_path_update(old_route, route,
1280 table);
1281 continue;
1282 }
1283
1284 list_delete_all_node(old_route->nh_list);
1285 ospf6_route_copy_nexthops(old_route, route);
1286 old_entry_updated = true;
1287
1288 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1289 o_path)) {
1290 if (o_path->area_id == route->path.area_id
1291 && ospf6_ls_origin_same(o_path, &route->path))
1292 break;
1293 }
1294
1295 /* New adv. router for a existing path add to paths list */
1296 if (o_path == NULL) {
1297 ecmp_path = ospf6_path_dup(&route->path);
1298
1299 /* Add a nh_list to new ecmp path */
1300 ospf6_copy_nexthops(ecmp_path->nh_list, route->nh_list);
1301
1302 /* Add the new path to route's path list */
1303 listnode_add_sort(old_route->paths, ecmp_path);
1304
1305 if (is_debug) {
1306 zlog_debug(
1307 "%s: route %pFX cost %u another path %pI4 added with nh %u, effective paths %u nh %u",
1308 __func__, &route->prefix,
1309 old_route->path.cost,
1310 &ecmp_path->origin.adv_router,
1311 listcount(ecmp_path->nh_list),
1312 old_route->paths
1313 ? listcount(old_route->paths)
1314 : 0,
1315 listcount(old_route->nh_list));
1316 }
1317 } else {
1318 struct ospf6_route *tmp_route;
1319
1320 tmp_route = ospf6_route_create(oa->ospf6);
1321
1322 ospf6_copy_nexthops(tmp_route->nh_list,
1323 o_path->nh_list);
1324
1325 if (!ospf6_route_cmp_nexthops(tmp_route, route)) {
1326 /* adv. router exists in the list, update nhs */
1327 list_delete_all_node(o_path->nh_list);
1328 ospf6_copy_nexthops(o_path->nh_list,
1329 route->nh_list);
1330 ospf6_route_delete(tmp_route);
1331 } else {
1332 /* adv. router has no change in nhs */
1333 old_entry_updated = false;
1334 ospf6_route_delete(tmp_route);
1335 continue;
1336 }
1337 }
1338
1339 if (is_debug)
1340 zlog_debug(
1341 "%s: Update route: %s %p old cost %u new cost %u nh %u",
1342 __func__, buf, (void *)old_route,
1343 old_route->path.cost, route->path.cost,
1344 listcount(old_route->nh_list));
1345
1346 /* For Inter-Prefix route: Update RIB/FIB,
1347 * For Inter-Router trigger summary update
1348 */
1349 if (table->hook_add)
1350 (*table->hook_add)(old_route);
1351
1352 break;
1353 }
1354
1355 /* If the old entry is not updated and old entry not found or old entry
1356 * does not match with the new entry then add the new route
1357 */
1358 if (old_entry_updated == false) {
1359 if ((old == NULL) || (old->type != route->type)
1360 || (old->path.type != route->path.type)
1361 || (old->path.cost != route->path.cost))
1362 add_route = true;
1363 }
1364
1365 if (add_route) {
1366 if (is_debug) {
1367 zlog_debug(
1368 "%s: Install new route: %s cost %u nh %u adv_router %pI4",
1369 __func__, buf, route->path.cost,
1370 listcount(route->nh_list),
1371 &route->path.origin.adv_router);
1372 }
1373
1374 path = ospf6_path_dup(&route->path);
1375 ospf6_copy_nexthops(path->nh_list, abr_entry->nh_list);
1376 listnode_add_sort(route->paths, path);
1377 /* ospf6_ia_add_nw_route (table, &prefix, route); */
1378 ospf6_route_add(route, table);
1379 } else
1380 /* if we did not add the route remove it */
1381 ospf6_route_delete(route);
1382 }
1383
1384 void ospf6_abr_examin_brouter(uint32_t router_id, struct ospf6_route *route,
1385 struct ospf6 *ospf6)
1386 {
1387 struct ospf6_lsa *lsa;
1388 struct ospf6_area *oa;
1389 uint16_t type;
1390
1391 oa = ospf6_area_lookup(route->path.area_id, ospf6);
1392 /*
1393 * It is possible to designate a non backbone
1394 * area first. If that is the case safely
1395 * fall out of this function.
1396 */
1397 if (oa == NULL)
1398 return;
1399
1400 type = htons(OSPF6_LSTYPE_INTER_ROUTER);
1401 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1402 ospf6_abr_examin_summary(lsa, oa);
1403
1404 type = htons(OSPF6_LSTYPE_INTER_PREFIX);
1405 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router_id, lsa))
1406 ospf6_abr_examin_summary(lsa, oa);
1407 }
1408
1409 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
1410 {
1411 struct ospf6_route *route;
1412
1413 if (IS_OSPF6_DEBUG_ABR)
1414 zlog_debug("Re-examining Inter-Prefix Summaries");
1415
1416 for (route = ospf6_route_head(o->route_table); route;
1417 route = ospf6_route_next(route))
1418 ospf6_abr_originate_summary(route, o);
1419
1420 if (IS_OSPF6_DEBUG_ABR)
1421 zlog_debug("Finished re-examining Inter-Prefix Summaries");
1422 }
1423
1424
1425 /* Display functions */
1426 static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1427 char *buf, int buflen,
1428 int pos)
1429 {
1430 struct ospf6_inter_prefix_lsa *prefix_lsa;
1431 struct in6_addr in6;
1432 char tbuf[16];
1433
1434 if (lsa != NULL) {
1435 prefix_lsa =
1436 (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1437 lsa->header);
1438
1439 ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
1440 if (buf) {
1441 inet_ntop(AF_INET6, &in6, buf, buflen);
1442 snprintf(tbuf, sizeof(tbuf), "/%d",
1443 prefix_lsa->prefix.prefix_length);
1444 strlcat(buf, tbuf, buflen);
1445 }
1446 }
1447
1448 return (buf);
1449 }
1450
1451 static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
1452 struct ospf6_lsa *lsa,
1453 json_object *json_obj,
1454 bool use_json)
1455 {
1456 struct ospf6_inter_prefix_lsa *prefix_lsa;
1457 char buf[INET6_ADDRSTRLEN];
1458
1459 prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
1460 lsa->header);
1461
1462 if (use_json) {
1463 json_object_int_add(
1464 json_obj, "metric",
1465 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1466 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1467 buf, sizeof(buf));
1468 json_object_string_add(json_obj, "prefixOptions", buf);
1469 json_object_string_add(
1470 json_obj, "prefix",
1471 ospf6_inter_area_prefix_lsa_get_prefix_str(
1472 lsa, buf, sizeof(buf), 0));
1473 } else {
1474 vty_out(vty, " Metric: %lu\n",
1475 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa));
1476
1477 ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options,
1478 buf, sizeof(buf));
1479 vty_out(vty, " Prefix Options: %s\n", buf);
1480
1481 vty_out(vty, " Prefix: %s\n",
1482 ospf6_inter_area_prefix_lsa_get_prefix_str(
1483 lsa, buf, sizeof(buf), 0));
1484 }
1485
1486 return 0;
1487 }
1488
1489 static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
1490 char *buf, int buflen,
1491 int pos)
1492 {
1493 struct ospf6_inter_router_lsa *router_lsa;
1494
1495 if (lsa != NULL) {
1496 router_lsa =
1497 (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1498 lsa->header);
1499
1500
1501 if (buf)
1502 inet_ntop(AF_INET, &router_lsa->router_id, buf, buflen);
1503 }
1504
1505 return (buf);
1506 }
1507
1508 static int ospf6_inter_area_router_lsa_show(struct vty *vty,
1509 struct ospf6_lsa *lsa,
1510 json_object *json_obj,
1511 bool use_json)
1512 {
1513 struct ospf6_inter_router_lsa *router_lsa;
1514 char buf[64];
1515
1516 router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
1517 lsa->header);
1518
1519 ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
1520 if (use_json) {
1521 json_object_string_add(json_obj, "options", buf);
1522 json_object_int_add(
1523 json_obj, "metric",
1524 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1525 } else {
1526 vty_out(vty, " Options: %s\n", buf);
1527 vty_out(vty, " Metric: %lu\n",
1528 (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa));
1529 }
1530
1531 inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf));
1532 if (use_json)
1533 json_object_string_add(json_obj, "destinationRouterId", buf);
1534 else
1535 vty_out(vty, " Destination Router ID: %s\n", buf);
1536
1537 return 0;
1538 }
1539
1540 /* Debug commands */
1541 DEFUN (debug_ospf6_abr,
1542 debug_ospf6_abr_cmd,
1543 "debug ospf6 abr",
1544 DEBUG_STR
1545 OSPF6_STR
1546 "Debug OSPFv3 ABR function\n"
1547 )
1548 {
1549 OSPF6_DEBUG_ABR_ON();
1550 return CMD_SUCCESS;
1551 }
1552
1553 DEFUN (no_debug_ospf6_abr,
1554 no_debug_ospf6_abr_cmd,
1555 "no debug ospf6 abr",
1556 NO_STR
1557 DEBUG_STR
1558 OSPF6_STR
1559 "Debug OSPFv3 ABR function\n"
1560 )
1561 {
1562 OSPF6_DEBUG_ABR_OFF();
1563 return CMD_SUCCESS;
1564 }
1565
1566 int config_write_ospf6_debug_abr(struct vty *vty)
1567 {
1568 if (IS_OSPF6_DEBUG_ABR)
1569 vty_out(vty, "debug ospf6 abr\n");
1570 return 0;
1571 }
1572
1573 void install_element_ospf6_debug_abr(void)
1574 {
1575 install_element(ENABLE_NODE, &debug_ospf6_abr_cmd);
1576 install_element(ENABLE_NODE, &no_debug_ospf6_abr_cmd);
1577 install_element(CONFIG_NODE, &debug_ospf6_abr_cmd);
1578 install_element(CONFIG_NODE, &no_debug_ospf6_abr_cmd);
1579 }
1580
1581 static struct ospf6_lsa_handler inter_prefix_handler = {
1582 .lh_type = OSPF6_LSTYPE_INTER_PREFIX,
1583 .lh_name = "Inter-Prefix",
1584 .lh_short_name = "IAP",
1585 .lh_show = ospf6_inter_area_prefix_lsa_show,
1586 .lh_get_prefix_str = ospf6_inter_area_prefix_lsa_get_prefix_str,
1587 .lh_debug = 0};
1588
1589 static struct ospf6_lsa_handler inter_router_handler = {
1590 .lh_type = OSPF6_LSTYPE_INTER_ROUTER,
1591 .lh_name = "Inter-Router",
1592 .lh_short_name = "IAR",
1593 .lh_show = ospf6_inter_area_router_lsa_show,
1594 .lh_get_prefix_str = ospf6_inter_area_router_lsa_get_prefix_str,
1595 .lh_debug = 0};
1596
1597 void ospf6_abr_init(void)
1598 {
1599 ospf6_install_lsa_handler(&inter_prefix_handler);
1600 ospf6_install_lsa_handler(&inter_router_handler);
1601 }