blob: 7eb8f09c19faa6df1a93b41fc51f256651d582b3 [file] [log] [blame]
hasso049207c2004-08-04 20:02:13 +00001/*
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
18 * along with GNU Zebra; see the file COPYING. If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "log.h"
26#include "prefix.h"
27#include "table.h"
28#include "vty.h"
29#include "linklist.h"
30#include "command.h"
hasso3b687352004-08-19 06:56:53 +000031#include "thread.h"
hasso049207c2004-08-04 20:02:13 +000032
33#include "ospf6_proto.h"
34#include "ospf6_route.h"
35#include "ospf6_lsa.h"
36#include "ospf6_route.h"
37#include "ospf6_lsdb.h"
hasso6452df02004-08-15 05:52:07 +000038#include "ospf6_message.h"
39
hasso049207c2004-08-04 20:02:13 +000040#include "ospf6_top.h"
41#include "ospf6_area.h"
42#include "ospf6_interface.h"
hasso6452df02004-08-15 05:52:07 +000043#include "ospf6_neighbor.h"
44
hasso6452df02004-08-15 05:52:07 +000045#include "ospf6_flood.h"
hasso3b687352004-08-19 06:56:53 +000046#include "ospf6_intra.h"
47#include "ospf6_abr.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
49
50unsigned char conf_debug_ospf6_abr;
51
hasso6452df02004-08-15 05:52:07 +000052int
53ospf6_is_router_abr (struct ospf6 *o)
54{
hasso52dc7ee2004-09-23 19:18:23 +000055 struct listnode *node;
hasso6452df02004-08-15 05:52:07 +000056 struct ospf6_area *oa;
57 int area_count = 0;
58
paul1eb8ef22005-04-07 07:30:20 +000059 for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa))
60 if (IS_AREA_ENABLED (oa))
61 area_count++;
hasso6452df02004-08-15 05:52:07 +000062
63 if (area_count > 1)
64 return 1;
65 return 0;
66}
67
hasso3b687352004-08-19 06:56:53 +000068void
69ospf6_abr_enable_area (struct ospf6_area *area)
70{
71 struct ospf6_area *oa;
72 struct ospf6_route *ro;
paul1eb8ef22005-04-07 07:30:20 +000073 struct listnode *node, *nnode;
hasso3b687352004-08-19 06:56:53 +000074
paul1eb8ef22005-04-07 07:30:20 +000075 for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
hasso3b687352004-08-19 06:56:53 +000076 {
hasso3b687352004-08-19 06:56:53 +000077 /* update B bit for each area */
78 OSPF6_ROUTER_LSA_SCHEDULE (oa);
79
80 /* install other area's configured address range */
81 if (oa != area)
82 {
83 for (ro = ospf6_route_head (oa->range_table); ro;
84 ro = ospf6_route_next (ro))
hasso4846ef62004-09-03 06:04:00 +000085 {
86 if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
87 ospf6_abr_originate_summary_to_area (ro, area);
88 }
hasso3b687352004-08-19 06:56:53 +000089 }
90 }
91
92 /* install calculated routes to border routers */
93 for (ro = ospf6_route_head (area->ospf6->brouter_table); ro;
94 ro = ospf6_route_next (ro))
95 ospf6_abr_originate_summary_to_area (ro, area);
96
97 /* install calculated routes to network (may be rejected by ranges) */
98 for (ro = ospf6_route_head (area->ospf6->route_table); ro;
99 ro = ospf6_route_next (ro))
100 ospf6_abr_originate_summary_to_area (ro, area);
101}
102
103void
104ospf6_abr_disable_area (struct ospf6_area *area)
105{
106 struct ospf6_area *oa;
107 struct ospf6_route *ro;
108 struct ospf6_lsa *old;
paul1eb8ef22005-04-07 07:30:20 +0000109 struct listnode *node, *nnode;
hasso3b687352004-08-19 06:56:53 +0000110
111 /* Withdraw all summary prefixes previously originated */
112 for (ro = ospf6_route_head (area->summary_prefix); ro;
113 ro = ospf6_route_next (ro))
114 {
115 old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
116 area->ospf6->router_id, area->lsdb);
117 if (old)
118 ospf6_lsa_purge (old);
119 ospf6_route_remove (ro, area->summary_prefix);
120 }
121
122 /* Withdraw all summary router-routes previously originated */
123 for (ro = ospf6_route_head (area->summary_router); ro;
124 ro = ospf6_route_next (ro))
125 {
126 old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
127 area->ospf6->router_id, area->lsdb);
128 if (old)
129 ospf6_lsa_purge (old);
130 ospf6_route_remove (ro, area->summary_router);
131 }
132
133 /* Schedule Router-LSA for each area (ABR status may change) */
paul1eb8ef22005-04-07 07:30:20 +0000134 for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa))
135 /* update B bit for each area */
136 OSPF6_ROUTER_LSA_SCHEDULE (oa);
hasso3b687352004-08-19 06:56:53 +0000137}
138
hasso049207c2004-08-04 20:02:13 +0000139/* RFC 2328 12.4.3. Summary-LSAs */
140void
hasso6452df02004-08-15 05:52:07 +0000141ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
142 struct ospf6_area *area)
hasso049207c2004-08-04 20:02:13 +0000143{
144 struct ospf6_lsa *lsa, *old = NULL;
145 struct ospf6_interface *oi;
146 struct ospf6_route *summary, *range = NULL;
147 struct ospf6_area *route_area;
148 char buffer[OSPF6_MAX_LSASIZE];
149 struct ospf6_lsa_header *lsa_header;
150 caddr_t p;
151 struct ospf6_inter_prefix_lsa *prefix_lsa;
hasso6452df02004-08-15 05:52:07 +0000152 struct ospf6_inter_router_lsa *router_lsa;
153 struct ospf6_route_table *summary_table = NULL;
154 u_int16_t type;
hasso1e058382004-09-01 21:36:14 +0000155 char buf[64];
156 int is_debug = 0;
hasso049207c2004-08-04 20:02:13 +0000157
hasso1e058382004-09-01 21:36:14 +0000158 if (route->type == OSPF6_DEST_TYPE_ROUTER)
hasso6452df02004-08-15 05:52:07 +0000159 {
hasso1e058382004-09-01 21:36:14 +0000160 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER))
hasso6452df02004-08-15 05:52:07 +0000161 {
hasso1e058382004-09-01 21:36:14 +0000162 is_debug++;
hasso3b687352004-08-19 06:56:53 +0000163 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
hasso6452df02004-08-15 05:52:07 +0000164 buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000165 zlog_debug ("Originating summary in area %s for ASBR %s",
166 area->name, buf);
hasso6452df02004-08-15 05:52:07 +0000167 }
hasso1e058382004-09-01 21:36:14 +0000168 summary_table = area->summary_router;
169 }
170 else
171 {
172 if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX))
hasso6452df02004-08-15 05:52:07 +0000173 {
hasso1e058382004-09-01 21:36:14 +0000174 is_debug++;
hasso6452df02004-08-15 05:52:07 +0000175 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000176 zlog_debug ("Originating summary in area %s for %s",
177 area->name, buf);
hasso6452df02004-08-15 05:52:07 +0000178 }
hasso1e058382004-09-01 21:36:14 +0000179 summary_table = area->summary_prefix;
hasso6452df02004-08-15 05:52:07 +0000180 }
181
hasso6452df02004-08-15 05:52:07 +0000182 summary = ospf6_route_lookup (&route->prefix, summary_table);
hasso049207c2004-08-04 20:02:13 +0000183 if (summary)
hasso6452df02004-08-15 05:52:07 +0000184 old = ospf6_lsdb_lookup (summary->path.origin.type,
hasso049207c2004-08-04 20:02:13 +0000185 summary->path.origin.id,
186 area->ospf6->router_id, area->lsdb);
187
188 /* if this route has just removed, remove corresponding LSA */
189 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
190 {
hasso1e058382004-09-01 21:36:14 +0000191 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000192 zlog_debug ("The route has just removed, purge previous LSA");
hasso6452df02004-08-15 05:52:07 +0000193 if (summary)
194 ospf6_route_remove (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000195 if (old)
hasso6452df02004-08-15 05:52:07 +0000196 ospf6_lsa_purge (old);
hasso049207c2004-08-04 20:02:13 +0000197 return;
198 }
199
hasso6452df02004-08-15 05:52:07 +0000200 /* Only destination type network, range or ASBR are considered */
201 if (route->type != OSPF6_DEST_TYPE_NETWORK &&
202 route->type != OSPF6_DEST_TYPE_RANGE &&
203 (route->type != OSPF6_DEST_TYPE_ROUTER ||
204 ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
hasso049207c2004-08-04 20:02:13 +0000205 {
hasso1e058382004-09-01 21:36:14 +0000206 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000207 zlog_debug ("Route type is none of network, range nor ASBR, withdraw");
hasso6452df02004-08-15 05:52:07 +0000208 if (summary)
209 ospf6_route_remove (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000210 if (old)
hasso6452df02004-08-15 05:52:07 +0000211 ospf6_lsa_purge (old);
hasso049207c2004-08-04 20:02:13 +0000212 return;
213 }
214
215 /* AS External routes are never considered */
216 if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
217 route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
218 {
hasso1e058382004-09-01 21:36:14 +0000219 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000220 zlog_debug ("Path type is external, withdraw");
hasso6452df02004-08-15 05:52:07 +0000221 if (summary)
222 ospf6_route_remove (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000223 if (old)
hasso6452df02004-08-15 05:52:07 +0000224 ospf6_lsa_purge (old);
hasso049207c2004-08-04 20:02:13 +0000225 return;
226 }
227
228 /* do not generate if the path's area is the same as target area */
229 if (route->path.area_id == area->area_id)
230 {
hasso1e058382004-09-01 21:36:14 +0000231 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000232 zlog_debug ("The route is in the area itself, ignore");
hasso6452df02004-08-15 05:52:07 +0000233 if (summary)
234 ospf6_route_remove (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000235 if (old)
hasso6452df02004-08-15 05:52:07 +0000236 ospf6_lsa_purge (old);
hasso049207c2004-08-04 20:02:13 +0000237 return;
238 }
239
240 /* do not generate if the nexthops belongs to the target area */
241 oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
hasso6452df02004-08-15 05:52:07 +0000242 if (oi && oi->area && oi->area == area)
hasso049207c2004-08-04 20:02:13 +0000243 {
hasso1e058382004-09-01 21:36:14 +0000244 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000245 zlog_debug ("The route's nexthop is in the same area, ignore");
hasso6452df02004-08-15 05:52:07 +0000246 if (summary)
247 ospf6_route_remove (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000248 if (old)
hasso6452df02004-08-15 05:52:07 +0000249 ospf6_lsa_purge (old);
hasso049207c2004-08-04 20:02:13 +0000250 return;
251 }
252
hasso6452df02004-08-15 05:52:07 +0000253 /* do not generate if the route cost is greater or equal to LSInfinity */
254 if (route->path.cost >= LS_INFINITY)
255 {
hasso1e058382004-09-01 21:36:14 +0000256 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000257 zlog_debug ("The cost exceeds LSInfinity, withdraw");
hasso6452df02004-08-15 05:52:07 +0000258 if (summary)
259 ospf6_route_remove (summary, summary_table);
260 if (old)
261 ospf6_lsa_purge (old);
262 return;
263 }
264
265 /* if this is a route to ASBR */
266 if (route->type == OSPF6_DEST_TYPE_ROUTER)
267 {
268 /* Only the prefered best path is considered */
269 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
270 {
hasso1e058382004-09-01 21:36:14 +0000271 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000272 zlog_debug ("This is the secondary path to the ASBR, ignore");
hasso6452df02004-08-15 05:52:07 +0000273 if (summary)
274 ospf6_route_remove (summary, summary_table);
275 if (old)
276 ospf6_lsa_purge (old);
277 return;
278 }
279
280 /* Do not generate if the area is stub */
281 /* XXX */
282 }
283
284 /* if this is an intra-area route, this may be suppressed by aggregation */
285 if (route->type == OSPF6_DEST_TYPE_NETWORK &&
286 route->path.type == OSPF6_PATH_TYPE_INTRA)
287 {
288 /* search for configured address range for the route's area */
289 route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
290 assert (route_area);
291 range = ospf6_route_lookup_bestmatch (&route->prefix,
292 route_area->range_table);
293
294 /* ranges are ignored when originate backbone routes to transit area.
295 Otherwise, if ranges are configured, the route is suppressed. */
296 if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
297 (route->path.area_id != BACKBONE_AREA_ID ||
298 ! IS_AREA_TRANSIT (area)))
299 {
hasso1e058382004-09-01 21:36:14 +0000300 if (is_debug)
hasso6452df02004-08-15 05:52:07 +0000301 {
hasso6452df02004-08-15 05:52:07 +0000302 prefix2str (&range->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000303 zlog_debug ("Suppressed by range %s of area %s",
hasso6452df02004-08-15 05:52:07 +0000304 buf, route_area->name);
305 }
306
307 if (summary)
308 ospf6_route_remove (summary, summary_table);
309 if (old)
310 ospf6_lsa_purge (old);
311 return;
312 }
313 }
314
315 /* If this is a configured address range */
316 if (route->type == OSPF6_DEST_TYPE_RANGE)
317 {
318 /* If DoNotAdvertise is set */
319 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
320 {
hasso1e058382004-09-01 21:36:14 +0000321 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000322 zlog_debug ("This is the range with DoNotAdvertise set. ignore");
hasso6452df02004-08-15 05:52:07 +0000323 if (summary)
324 ospf6_route_remove (summary, summary_table);
325 if (old)
326 ospf6_lsa_purge (old);
327 return;
328 }
329
330 /* Whether the route have active longer prefix */
331 if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
332 {
hasso1e058382004-09-01 21:36:14 +0000333 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000334 zlog_debug ("The range is not active. withdraw");
hasso6452df02004-08-15 05:52:07 +0000335 if (summary)
336 ospf6_route_remove (summary, summary_table);
337 if (old)
338 ospf6_lsa_purge (old);
339 return;
340 }
341 }
342
hasso049207c2004-08-04 20:02:13 +0000343 /* the route is going to be originated. store it in area's summary_table */
344 if (summary == NULL)
345 {
346 summary = ospf6_route_copy (route);
hasso6452df02004-08-15 05:52:07 +0000347 if (route->type == OSPF6_DEST_TYPE_NETWORK ||
348 route->type == OSPF6_DEST_TYPE_RANGE)
349 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
350 else
351 summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
hasso049207c2004-08-04 20:02:13 +0000352 summary->path.origin.adv_router = area->ospf6->router_id;
353 summary->path.origin.id =
354 ospf6_new_ls_id (summary->path.origin.type,
355 summary->path.origin.adv_router, area->lsdb);
hasso9428f2d2004-09-13 14:01:12 +0000356 summary = ospf6_route_add (summary, summary_table);
hasso049207c2004-08-04 20:02:13 +0000357 }
hasso6452df02004-08-15 05:52:07 +0000358 else
359 {
360 summary->type = route->type;
361 gettimeofday (&summary->changed, NULL);
362 }
363
364 summary->path.router_bits = route->path.router_bits;
365 summary->path.options[0] = route->path.options[0];
366 summary->path.options[1] = route->path.options[1];
367 summary->path.options[2] = route->path.options[2];
368 summary->path.prefix_options = route->path.prefix_options;
369 summary->path.area_id = area->area_id;
370 summary->path.type = OSPF6_PATH_TYPE_INTER;
371 summary->path.cost = route->path.cost;
372 summary->nexthop[0] = route->nexthop[0];
hasso049207c2004-08-04 20:02:13 +0000373
374 /* prepare buffer */
375 memset (buffer, 0, sizeof (buffer));
376 lsa_header = (struct ospf6_lsa_header *) buffer;
hasso049207c2004-08-04 20:02:13 +0000377
hasso6452df02004-08-15 05:52:07 +0000378 if (route->type == OSPF6_DEST_TYPE_ROUTER)
379 {
380 router_lsa = (struct ospf6_inter_router_lsa *)
381 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
382 p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);
hasso049207c2004-08-04 20:02:13 +0000383
hasso6452df02004-08-15 05:52:07 +0000384 /* Fill Inter-Area-Router-LSA */
385 router_lsa->options[0] = route->path.options[0];
386 router_lsa->options[1] = route->path.options[1];
387 router_lsa->options[2] = route->path.options[2];
388 OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
hasso3b687352004-08-19 06:56:53 +0000389 router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
hasso6452df02004-08-15 05:52:07 +0000390 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
391 }
392 else
393 {
394 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
395 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
396 p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);
hasso049207c2004-08-04 20:02:13 +0000397
hasso6452df02004-08-15 05:52:07 +0000398 /* Fill Inter-Area-Prefix-LSA */
399 OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
400 prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
401 prefix_lsa->prefix.prefix_options = route->path.prefix_options;
hasso049207c2004-08-04 20:02:13 +0000402
hasso6452df02004-08-15 05:52:07 +0000403 /* set Prefix */
404 memcpy (p, &route->prefix.u.prefix6,
405 OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
406 ospf6_prefix_apply_mask (&prefix_lsa->prefix);
407 p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
408 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
409 }
hasso049207c2004-08-04 20:02:13 +0000410
411 /* Fill LSA Header */
412 lsa_header->age = 0;
hasso6452df02004-08-15 05:52:07 +0000413 lsa_header->type = type;
hasso049207c2004-08-04 20:02:13 +0000414 lsa_header->id = summary->path.origin.id;
415 lsa_header->adv_router = area->ospf6->router_id;
416 lsa_header->seqnum =
417 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
418 lsa_header->adv_router, area->lsdb);
419 lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
420
421 /* LSA checksum */
422 ospf6_lsa_checksum (lsa_header);
423
424 /* create LSA */
425 lsa = ospf6_lsa_create (lsa_header);
hasso6452df02004-08-15 05:52:07 +0000426
hasso049207c2004-08-04 20:02:13 +0000427 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000428 ospf6_lsa_originate_area (lsa, area);
hasso049207c2004-08-04 20:02:13 +0000429}
430
431void
hasso6452df02004-08-15 05:52:07 +0000432ospf6_abr_range_update (struct ospf6_route *range)
433{
434 u_int32_t cost = 0;
435 struct ospf6_route *ro;
436
437 assert (range->type == OSPF6_DEST_TYPE_RANGE);
438
439 /* update range's cost and active flag */
440 for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table);
441 ro; ro = ospf6_route_match_next (&range->prefix, ro))
442 {
443 if (ro->path.area_id == range->path.area_id &&
444 ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE))
445 cost = MAX (cost, ro->path.cost);
446 }
447
448 if (range->path.cost != cost)
449 {
450 range->path.cost = cost;
451
452 if (range->path.cost)
453 SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
454 else
455 UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY);
456
457 ospf6_abr_originate_summary (range);
458 }
459}
460
461void
462ospf6_abr_originate_summary (struct ospf6_route *route)
hasso049207c2004-08-04 20:02:13 +0000463{
paul1eb8ef22005-04-07 07:30:20 +0000464 struct listnode *node, *nnode;
hasso049207c2004-08-04 20:02:13 +0000465 struct ospf6_area *oa;
hasso6452df02004-08-15 05:52:07 +0000466 struct ospf6_route *range = NULL;
hasso049207c2004-08-04 20:02:13 +0000467
hasso6452df02004-08-15 05:52:07 +0000468 if (route->type == OSPF6_DEST_TYPE_NETWORK)
469 {
470 oa = ospf6_area_lookup (route->path.area_id, ospf6);
471 range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table);
472 if (range)
473 ospf6_abr_range_update (range);
474 }
475
paul1eb8ef22005-04-07 07:30:20 +0000476 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
477 ospf6_abr_originate_summary_to_area (route, oa);
hasso049207c2004-08-04 20:02:13 +0000478}
479
480/* RFC 2328 16.2. Calculating the inter-area routes */
481void
482ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
483{
484 struct prefix prefix, abr_prefix;
485 struct ospf6_route_table *table = NULL;
486 struct ospf6_route *range, *route, *old = NULL;
487 struct ospf6_route *abr_entry;
hasso6452df02004-08-15 05:52:07 +0000488 u_char type = 0;
hasso049207c2004-08-04 20:02:13 +0000489 char options[3] = {0, 0, 0};
490 u_int8_t prefix_options = 0;
491 u_int32_t cost = 0;
hasso63069ad2004-09-02 13:01:01 +0000492 u_char router_bits = 0;
hasso049207c2004-08-04 20:02:13 +0000493 int i;
hassoccb59b12004-08-25 09:10:37 +0000494 char buf[64];
hasso1e058382004-09-01 21:36:14 +0000495 int is_debug = 0;
hasso3b687352004-08-19 06:56:53 +0000496
hasso049207c2004-08-04 20:02:13 +0000497 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
498 {
499 struct ospf6_inter_prefix_lsa *prefix_lsa;
hasso1e058382004-09-01 21:36:14 +0000500
501 if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
502 {
503 is_debug++;
hassoc6487d62004-12-24 06:00:11 +0000504 zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
hasso1e058382004-09-01 21:36:14 +0000505 }
506
hasso049207c2004-08-04 20:02:13 +0000507 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
508 OSPF6_LSA_HEADER_END (lsa->header);
509 prefix.family = AF_INET6;
510 prefix.prefixlen = prefix_lsa->prefix.prefix_length;
511 ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
hassoccb59b12004-08-25 09:10:37 +0000512 prefix2str (&prefix, buf, sizeof (buf));
hasso049207c2004-08-04 20:02:13 +0000513 table = oa->ospf6->route_table;
514 type = OSPF6_DEST_TYPE_NETWORK;
515 prefix_options = prefix_lsa->prefix.prefix_options;
516 cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
517 }
518 else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
519 {
520 struct ospf6_inter_router_lsa *router_lsa;
hasso1e058382004-09-01 21:36:14 +0000521
522 if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
523 {
524 is_debug++;
hassoc6487d62004-12-24 06:00:11 +0000525 zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
hasso1e058382004-09-01 21:36:14 +0000526 }
527
hasso049207c2004-08-04 20:02:13 +0000528 router_lsa = (struct ospf6_inter_router_lsa *)
529 OSPF6_LSA_HEADER_END (lsa->header);
530 ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
hassoccb59b12004-08-25 09:10:37 +0000531 inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
hasso049207c2004-08-04 20:02:13 +0000532 table = oa->ospf6->brouter_table;
533 type = OSPF6_DEST_TYPE_ROUTER;
534 options[0] = router_lsa->options[0];
535 options[1] = router_lsa->options[1];
536 options[2] = router_lsa->options[2];
537 cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
hasso63069ad2004-09-02 13:01:01 +0000538 SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
hasso049207c2004-08-04 20:02:13 +0000539 }
540 else
541 assert (0);
542
hassoccb59b12004-08-25 09:10:37 +0000543 /* Find existing route */
544 route = ospf6_route_lookup (&prefix, table);
545 if (route)
546 ospf6_route_lock (route);
547 while (route && ospf6_route_is_prefix (&prefix, route))
hasso049207c2004-08-04 20:02:13 +0000548 {
549 if (route->path.area_id == oa->area_id &&
550 route->path.origin.type == lsa->header->type &&
551 route->path.origin.id == lsa->header->id &&
552 route->path.origin.adv_router == lsa->header->adv_router)
553 old = route;
hassoccb59b12004-08-25 09:10:37 +0000554 route = ospf6_route_next (route);
hasso049207c2004-08-04 20:02:13 +0000555 }
556
557 /* (1) if cost == LSInfinity or if the LSA is MaxAge */
hasso3b687352004-08-19 06:56:53 +0000558 if (cost == LS_INFINITY)
hasso049207c2004-08-04 20:02:13 +0000559 {
hasso1e058382004-09-01 21:36:14 +0000560 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000561 zlog_debug ("cost is LS_INFINITY, ignore");
hasso3b687352004-08-19 06:56:53 +0000562 if (old)
hasso63069ad2004-09-02 13:01:01 +0000563 ospf6_route_remove (old, table);
hasso3b687352004-08-19 06:56:53 +0000564 return;
565 }
566 if (OSPF6_LSA_IS_MAXAGE (lsa))
567 {
hasso1e058382004-09-01 21:36:14 +0000568 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000569 zlog_debug ("LSA is MaxAge, ignore");
hasso049207c2004-08-04 20:02:13 +0000570 if (old)
hasso63069ad2004-09-02 13:01:01 +0000571 ospf6_route_remove (old, table);
hasso049207c2004-08-04 20:02:13 +0000572 return;
573 }
574
575 /* (2) if the LSA is self-originated, ignore */
576 if (lsa->header->adv_router == oa->ospf6->router_id)
577 {
hasso1e058382004-09-01 21:36:14 +0000578 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000579 zlog_debug ("LSA is self-originated, ignore");
hasso049207c2004-08-04 20:02:13 +0000580 if (old)
hasso63069ad2004-09-02 13:01:01 +0000581 ospf6_route_remove (old, table);
hasso049207c2004-08-04 20:02:13 +0000582 return;
583 }
584
585 /* (3) if the prefix is equal to an active configured address range */
hasso6452df02004-08-15 05:52:07 +0000586 if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
hasso049207c2004-08-04 20:02:13 +0000587 {
hasso6452df02004-08-15 05:52:07 +0000588 range = ospf6_route_lookup (&prefix, oa->range_table);
589 if (range)
590 {
hasso1e058382004-09-01 21:36:14 +0000591 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000592 zlog_debug ("Prefix is equal to address range, ignore");
hasso6452df02004-08-15 05:52:07 +0000593 if (old)
hasso63069ad2004-09-02 13:01:01 +0000594 ospf6_route_remove (old, table);
hasso6452df02004-08-15 05:52:07 +0000595 return;
596 }
hasso049207c2004-08-04 20:02:13 +0000597 }
598
599 /* (4) if the routing table entry for the ABR does not exist */
600 ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
601 abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
hasso6452df02004-08-15 05:52:07 +0000602 if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
hassoccb59b12004-08-25 09:10:37 +0000603 CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
hasso6452df02004-08-15 05:52:07 +0000604 ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
hasso049207c2004-08-04 20:02:13 +0000605 {
hasso1e058382004-09-01 21:36:14 +0000606 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000607 zlog_debug ("ABR router entry does not exist, ignore");
hasso049207c2004-08-04 20:02:13 +0000608 if (old)
hasso63069ad2004-09-02 13:01:01 +0000609 ospf6_route_remove (old, table);
hasso049207c2004-08-04 20:02:13 +0000610 return;
611 }
612
613 /* (5),(6),(7) the path preference is handled by the sorting
614 in the routing table. Always install the path by substituting
615 old route (if any). */
616 if (old)
hassoccb59b12004-08-25 09:10:37 +0000617 route = ospf6_route_copy (old);
hasso049207c2004-08-04 20:02:13 +0000618 else
619 route = ospf6_route_create ();
620
621 route->type = type;
622 route->prefix = prefix;
623 route->path.origin.type = lsa->header->type;
624 route->path.origin.id = lsa->header->id;
625 route->path.origin.adv_router = lsa->header->adv_router;
hasso63069ad2004-09-02 13:01:01 +0000626 route->path.router_bits = router_bits;
hasso049207c2004-08-04 20:02:13 +0000627 route->path.options[0] = options[0];
628 route->path.options[1] = options[1];
629 route->path.options[2] = options[2];
630 route->path.prefix_options = prefix_options;
631 route->path.area_id = oa->area_id;
632 route->path.type = OSPF6_PATH_TYPE_INTER;
633 route->path.cost = abr_entry->path.cost + cost;
634 for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
635 route->nexthop[i] = abr_entry->nexthop[i];
636
hasso1e058382004-09-01 21:36:14 +0000637 if (is_debug)
hassoc6487d62004-12-24 06:00:11 +0000638 zlog_debug ("Install route: %s", buf);
hasso049207c2004-08-04 20:02:13 +0000639 ospf6_route_add (route, table);
640}
641
hassoccb59b12004-08-25 09:10:37 +0000642void
643ospf6_abr_examin_brouter (u_int32_t router_id)
644{
645 struct ospf6_lsa *lsa;
646 struct ospf6_area *oa;
paul1eb8ef22005-04-07 07:30:20 +0000647 struct listnode *node, *nnode;
hassoccb59b12004-08-25 09:10:37 +0000648 u_int16_t type;
649
paul1eb8ef22005-04-07 07:30:20 +0000650 for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa))
hassoccb59b12004-08-25 09:10:37 +0000651 {
paul1eb8ef22005-04-07 07:30:20 +0000652 type = htons (OSPF6_LSTYPE_INTER_ROUTER);
hassoccb59b12004-08-25 09:10:37 +0000653 for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
654 lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
655 ospf6_abr_examin_summary (lsa, oa);
hassoccb59b12004-08-25 09:10:37 +0000656
paul1eb8ef22005-04-07 07:30:20 +0000657 type = htons (OSPF6_LSTYPE_INTER_PREFIX);
hassoccb59b12004-08-25 09:10:37 +0000658 for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa;
659 lsa = ospf6_lsdb_type_router_next (type, router_id, lsa))
660 ospf6_abr_examin_summary (lsa, oa);
661 }
662}
663
hasso049207c2004-08-04 20:02:13 +0000664
665/* Display functions */
666int
667ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
668{
669 struct ospf6_inter_prefix_lsa *prefix_lsa;
670 struct in6_addr in6;
671 char buf[64];
672
673 prefix_lsa = (struct ospf6_inter_prefix_lsa *)
674 OSPF6_LSA_HEADER_END (lsa->header);
675
676 vty_out (vty, " Metric: %lu%s",
677 (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL);
678
679 ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options,
680 buf, sizeof (buf));
681 vty_out (vty, " Prefix Options: %s%s", buf, VNL);
682
683 ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
684 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
685 vty_out (vty, " Prefix: %s/%d%s", buf,
686 prefix_lsa->prefix.prefix_length, VNL);
687
688 return 0;
689}
690
691int
692ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
693{
694 struct ospf6_inter_router_lsa *router_lsa;
695 char buf[64];
696
697 router_lsa = (struct ospf6_inter_router_lsa *)
698 OSPF6_LSA_HEADER_END (lsa->header);
699
700 ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf));
701 vty_out (vty, " Options: %s%s", buf, VNL);
702 vty_out (vty, " Metric: %lu%s",
703 (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
704 inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
705 vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
706
707 return 0;
708}
709
710/* Debug commands */
711DEFUN (debug_ospf6_abr,
712 debug_ospf6_abr_cmd,
713 "debug ospf6 abr",
714 DEBUG_STR
715 OSPF6_STR
716 "Debug OSPFv3 ABR function\n"
717 )
718{
719 OSPF6_DEBUG_ABR_ON ();
720 return CMD_SUCCESS;
721}
722
723DEFUN (no_debug_ospf6_abr,
724 no_debug_ospf6_abr_cmd,
725 "no debug ospf6 abr",
726 NO_STR
727 DEBUG_STR
728 OSPF6_STR
729 "Debug OSPFv3 ABR function\n"
730 )
731{
732 OSPF6_DEBUG_ABR_OFF ();
733 return CMD_SUCCESS;
734}
735
736int
737config_write_ospf6_debug_abr (struct vty *vty)
738{
739 if (IS_OSPF6_DEBUG_ABR)
740 vty_out (vty, "debug ospf6 abr%s", VNL);
741 return 0;
742}
743
744void
745install_element_ospf6_debug_abr ()
746{
747 install_element (ENABLE_NODE, &debug_ospf6_abr_cmd);
748 install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd);
749 install_element (CONFIG_NODE, &debug_ospf6_abr_cmd);
750 install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd);
751}
752
hasso6452df02004-08-15 05:52:07 +0000753struct ospf6_lsa_handler inter_prefix_handler =
754{
755 OSPF6_LSTYPE_INTER_PREFIX,
756 "Inter-Prefix",
757 ospf6_inter_area_prefix_lsa_show
758};
759
760struct ospf6_lsa_handler inter_router_handler =
761{
762 OSPF6_LSTYPE_INTER_ROUTER,
763 "Inter-Router",
764 ospf6_inter_area_router_lsa_show
765};
766
hasso049207c2004-08-04 20:02:13 +0000767void
768ospf6_abr_init ()
769{
hasso6452df02004-08-15 05:52:07 +0000770 ospf6_install_lsa_handler (&inter_prefix_handler);
771 ospf6_install_lsa_handler (&inter_router_handler);
hasso049207c2004-08-04 20:02:13 +0000772}
773
774