]>
Commit | Line | Data |
---|---|---|
049207c3 | 1 | /* |
2 | * Area Border Router function. | |
3 | * Copyright (C) 2004 Yasuhiro Ohara | |
4 | * | |
5 | * This file is part of GNU Zebra. | |
6 | * | |
7 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2, or (at your option) any | |
10 | * later version. | |
11 | * | |
12 | * GNU Zebra is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
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" | |
31 | ||
32 | #include "ospf6_proto.h" | |
33 | #include "ospf6_route.h" | |
34 | #include "ospf6_lsa.h" | |
35 | #include "ospf6_route.h" | |
36 | #include "ospf6_lsdb.h" | |
6452df09 | 37 | #include "ospf6_message.h" |
38 | ||
049207c3 | 39 | #include "ospf6_top.h" |
40 | #include "ospf6_area.h" | |
41 | #include "ospf6_interface.h" | |
6452df09 | 42 | #include "ospf6_neighbor.h" |
43 | ||
049207c3 | 44 | #include "ospf6_abr.h" |
6452df09 | 45 | #include "ospf6_flood.h" |
049207c3 | 46 | #include "ospf6d.h" |
47 | ||
48 | unsigned char conf_debug_ospf6_abr; | |
49 | ||
6452df09 | 50 | int |
51 | ospf6_is_router_abr (struct ospf6 *o) | |
52 | { | |
53 | listnode node; | |
54 | struct ospf6_area *oa; | |
55 | int area_count = 0; | |
56 | ||
57 | for (node = listhead (o->area_list); node; nextnode (node)) | |
58 | { | |
59 | oa = OSPF6_AREA (getdata (node)); | |
60 | if (IS_AREA_ENABLED (oa)) | |
61 | area_count++; | |
62 | } | |
63 | ||
64 | if (area_count > 1) | |
65 | return 1; | |
66 | return 0; | |
67 | } | |
68 | ||
049207c3 | 69 | /* RFC 2328 12.4.3. Summary-LSAs */ |
70 | void | |
6452df09 | 71 | ospf6_abr_originate_summary_to_area (struct ospf6_route *route, |
72 | struct ospf6_area *area) | |
049207c3 | 73 | { |
74 | struct ospf6_lsa *lsa, *old = NULL; | |
75 | struct ospf6_interface *oi; | |
76 | struct ospf6_route *summary, *range = NULL; | |
77 | struct ospf6_area *route_area; | |
78 | char buffer[OSPF6_MAX_LSASIZE]; | |
79 | struct ospf6_lsa_header *lsa_header; | |
80 | caddr_t p; | |
81 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
6452df09 | 82 | struct ospf6_inter_router_lsa *router_lsa; |
83 | struct ospf6_route_table *summary_table = NULL; | |
84 | u_int16_t type; | |
85 | ||
86 | if (IS_OSPF6_DEBUG_ABR) | |
87 | { | |
88 | char buf[64]; | |
89 | if (route->type == OSPF6_DEST_TYPE_ROUTER) | |
90 | { | |
91 | inet_ntop (AF_INET, | |
92 | &(ospf6_linkstate_prefix_adv_router (&route->prefix)), | |
93 | buf, sizeof (buf)); | |
94 | zlog_info ("Originating summary in area %s for ASBR %s", | |
95 | area->name, buf); | |
96 | } | |
97 | else | |
98 | { | |
99 | prefix2str (&route->prefix, buf, sizeof (buf)); | |
100 | zlog_info ("Originating summary in area %s for %s", | |
101 | area->name, buf); | |
102 | } | |
103 | } | |
049207c3 | 104 | |
6452df09 | 105 | if (route->type == OSPF6_DEST_TYPE_ROUTER) |
106 | summary_table = area->summary_router; | |
107 | else | |
108 | summary_table = area->summary_prefix; | |
109 | summary = ospf6_route_lookup (&route->prefix, summary_table); | |
049207c3 | 110 | if (summary) |
6452df09 | 111 | old = ospf6_lsdb_lookup (summary->path.origin.type, |
049207c3 | 112 | summary->path.origin.id, |
113 | area->ospf6->router_id, area->lsdb); | |
114 | ||
115 | /* if this route has just removed, remove corresponding LSA */ | |
116 | if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) | |
117 | { | |
6452df09 | 118 | if (IS_OSPF6_DEBUG_ABR) |
119 | zlog_info ("The route has just removed, purge previous LSA"); | |
120 | if (summary) | |
121 | ospf6_route_remove (summary, summary_table); | |
049207c3 | 122 | if (old) |
6452df09 | 123 | ospf6_lsa_purge (old); |
049207c3 | 124 | return; |
125 | } | |
126 | ||
6452df09 | 127 | /* Only destination type network, range or ASBR are considered */ |
128 | if (route->type != OSPF6_DEST_TYPE_NETWORK && | |
129 | route->type != OSPF6_DEST_TYPE_RANGE && | |
130 | (route->type != OSPF6_DEST_TYPE_ROUTER || | |
131 | ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) | |
049207c3 | 132 | { |
6452df09 | 133 | if (IS_OSPF6_DEBUG_ABR) |
134 | zlog_info ("Route type is none of network, range nor ASBR, withdraw"); | |
135 | if (summary) | |
136 | ospf6_route_remove (summary, summary_table); | |
049207c3 | 137 | if (old) |
6452df09 | 138 | ospf6_lsa_purge (old); |
049207c3 | 139 | return; |
140 | } | |
141 | ||
142 | /* AS External routes are never considered */ | |
143 | if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || | |
144 | route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) | |
145 | { | |
6452df09 | 146 | if (IS_OSPF6_DEBUG_ABR) |
147 | zlog_info ("Path type is external, withdraw"); | |
148 | if (summary) | |
149 | ospf6_route_remove (summary, summary_table); | |
049207c3 | 150 | if (old) |
6452df09 | 151 | ospf6_lsa_purge (old); |
049207c3 | 152 | return; |
153 | } | |
154 | ||
6452df09 | 155 | /* do not generate if the path's area is the same as target area */ |
156 | if (route->path.area_id == area->area_id) | |
049207c3 | 157 | { |
6452df09 | 158 | if (IS_OSPF6_DEBUG_ABR) |
159 | zlog_info ("The route is in the area itself, ignore"); | |
160 | if (summary) | |
161 | ospf6_route_remove (summary, summary_table); | |
049207c3 | 162 | if (old) |
6452df09 | 163 | ospf6_lsa_purge (old); |
049207c3 | 164 | return; |
165 | } | |
166 | ||
6452df09 | 167 | /* do not generate if the nexthops belongs to the target area */ |
168 | oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex); | |
169 | if (oi && oi->area && oi->area == area) | |
049207c3 | 170 | { |
6452df09 | 171 | if (IS_OSPF6_DEBUG_ABR) |
172 | zlog_info ("The route's nexthop is in the same area, ignore"); | |
173 | if (summary) | |
174 | ospf6_route_remove (summary, summary_table); | |
175 | if (old) | |
176 | ospf6_lsa_purge (old); | |
177 | return; | |
049207c3 | 178 | } |
179 | ||
6452df09 | 180 | /* do not generate if the route cost is greater or equal to LSInfinity */ |
181 | if (route->path.cost >= LS_INFINITY) | |
049207c3 | 182 | { |
6452df09 | 183 | if (IS_OSPF6_DEBUG_ABR) |
184 | zlog_info ("The cost exceeds LSInfinity, withdraw"); | |
185 | if (summary) | |
186 | ospf6_route_remove (summary, summary_table); | |
049207c3 | 187 | if (old) |
6452df09 | 188 | ospf6_lsa_purge (old); |
049207c3 | 189 | return; |
190 | } | |
191 | ||
6452df09 | 192 | /* if this is a route to ASBR */ |
193 | if (route->type == OSPF6_DEST_TYPE_ROUTER) | |
049207c3 | 194 | { |
6452df09 | 195 | /* Only the prefered best path is considered */ |
196 | if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) | |
197 | { | |
198 | if (IS_OSPF6_DEBUG_ABR) | |
199 | zlog_info ("This is the secondary path to the ASBR, ignore"); | |
200 | if (summary) | |
201 | ospf6_route_remove (summary, summary_table); | |
202 | if (old) | |
203 | ospf6_lsa_purge (old); | |
204 | return; | |
205 | } | |
206 | ||
207 | /* Do not generate if the area is stub */ | |
208 | /* XXX */ | |
049207c3 | 209 | } |
210 | ||
6452df09 | 211 | /* if this is an intra-area route, this may be suppressed by aggregation */ |
212 | if (route->type == OSPF6_DEST_TYPE_NETWORK && | |
213 | route->path.type == OSPF6_PATH_TYPE_INTRA) | |
049207c3 | 214 | { |
6452df09 | 215 | /* search for configured address range for the route's area */ |
216 | route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); | |
217 | assert (route_area); | |
218 | range = ospf6_route_lookup_bestmatch (&route->prefix, | |
219 | route_area->range_table); | |
220 | ||
221 | /* ranges are ignored when originate backbone routes to transit area. | |
222 | Otherwise, if ranges are configured, the route is suppressed. */ | |
223 | if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && | |
224 | (route->path.area_id != BACKBONE_AREA_ID || | |
225 | ! IS_AREA_TRANSIT (area))) | |
226 | { | |
227 | if (IS_OSPF6_DEBUG_ABR) | |
228 | { | |
229 | char buf[64]; | |
230 | prefix2str (&range->prefix, buf, sizeof (buf)); | |
231 | zlog_info ("Suppressed by range %s of area %s", | |
232 | buf, route_area->name); | |
233 | } | |
234 | ||
235 | if (summary) | |
236 | ospf6_route_remove (summary, summary_table); | |
237 | if (old) | |
238 | ospf6_lsa_purge (old); | |
239 | return; | |
240 | } | |
241 | } | |
242 | ||
243 | /* If this is a configured address range */ | |
244 | if (route->type == OSPF6_DEST_TYPE_RANGE) | |
245 | { | |
246 | /* If DoNotAdvertise is set */ | |
247 | if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) | |
248 | { | |
249 | if (IS_OSPF6_DEBUG_ABR) | |
250 | zlog_info ("This is the range with DoNotAdvertise set. ignore"); | |
251 | if (summary) | |
252 | ospf6_route_remove (summary, summary_table); | |
253 | if (old) | |
254 | ospf6_lsa_purge (old); | |
255 | return; | |
256 | } | |
257 | ||
258 | /* Whether the route have active longer prefix */ | |
259 | if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) | |
260 | { | |
261 | if (IS_OSPF6_DEBUG_ABR) | |
262 | zlog_info ("The range is not active. withdraw"); | |
263 | if (summary) | |
264 | ospf6_route_remove (summary, summary_table); | |
265 | if (old) | |
266 | ospf6_lsa_purge (old); | |
267 | return; | |
268 | } | |
049207c3 | 269 | } |
270 | ||
271 | /* the route is going to be originated. store it in area's summary_table */ | |
272 | if (summary == NULL) | |
273 | { | |
274 | summary = ospf6_route_copy (route); | |
6452df09 | 275 | if (route->type == OSPF6_DEST_TYPE_NETWORK || |
276 | route->type == OSPF6_DEST_TYPE_RANGE) | |
277 | summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
278 | else | |
279 | summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); | |
049207c3 | 280 | summary->path.origin.adv_router = area->ospf6->router_id; |
281 | summary->path.origin.id = | |
282 | ospf6_new_ls_id (summary->path.origin.type, | |
283 | summary->path.origin.adv_router, area->lsdb); | |
6452df09 | 284 | ospf6_route_add (summary, summary_table); |
285 | } | |
286 | else | |
287 | { | |
288 | summary->type = route->type; | |
289 | gettimeofday (&summary->changed, NULL); | |
049207c3 | 290 | } |
291 | ||
6452df09 | 292 | summary->path.router_bits = route->path.router_bits; |
293 | summary->path.options[0] = route->path.options[0]; | |
294 | summary->path.options[1] = route->path.options[1]; | |
295 | summary->path.options[2] = route->path.options[2]; | |
296 | summary->path.prefix_options = route->path.prefix_options; | |
297 | summary->path.area_id = area->area_id; | |
298 | summary->path.type = OSPF6_PATH_TYPE_INTER; | |
299 | summary->path.cost = route->path.cost; | |
300 | summary->nexthop[0] = route->nexthop[0]; | |
301 | ||
049207c3 | 302 | /* prepare buffer */ |
303 | memset (buffer, 0, sizeof (buffer)); | |
304 | lsa_header = (struct ospf6_lsa_header *) buffer; | |
049207c3 | 305 | |
6452df09 | 306 | if (route->type == OSPF6_DEST_TYPE_ROUTER) |
307 | { | |
308 | router_lsa = (struct ospf6_inter_router_lsa *) | |
309 | ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); | |
310 | p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); | |
311 | ||
312 | /* Fill Inter-Area-Router-LSA */ | |
313 | router_lsa->options[0] = route->path.options[0]; | |
314 | router_lsa->options[1] = route->path.options[1]; | |
315 | router_lsa->options[2] = route->path.options[2]; | |
316 | OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); | |
317 | router_lsa->router_id = | |
318 | ospf6_linkstate_prefix_adv_router (&route->prefix); | |
319 | type = htons (OSPF6_LSTYPE_INTER_ROUTER); | |
320 | } | |
321 | else | |
322 | { | |
323 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
324 | ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); | |
325 | p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); | |
326 | ||
327 | /* Fill Inter-Area-Prefix-LSA */ | |
328 | OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); | |
329 | prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; | |
330 | prefix_lsa->prefix.prefix_options = route->path.prefix_options; | |
331 | ||
332 | /* set Prefix */ | |
333 | memcpy (p, &route->prefix.u.prefix6, | |
334 | OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); | |
335 | ospf6_prefix_apply_mask (&prefix_lsa->prefix); | |
336 | p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); | |
337 | type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
338 | } | |
049207c3 | 339 | |
340 | /* Fill LSA Header */ | |
341 | lsa_header->age = 0; | |
6452df09 | 342 | lsa_header->type = type; |
049207c3 | 343 | lsa_header->id = summary->path.origin.id; |
344 | lsa_header->adv_router = area->ospf6->router_id; | |
345 | lsa_header->seqnum = | |
346 | ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, | |
347 | lsa_header->adv_router, area->lsdb); | |
348 | lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header); | |
349 | ||
350 | /* LSA checksum */ | |
351 | ospf6_lsa_checksum (lsa_header); | |
352 | ||
353 | /* create LSA */ | |
354 | lsa = ospf6_lsa_create (lsa_header); | |
6452df09 | 355 | |
356 | if (IS_OSPF6_DEBUG_ABR) | |
357 | zlog_info ("Originate as %s", lsa->name); | |
049207c3 | 358 | |
359 | /* Originate */ | |
6452df09 | 360 | ospf6_lsa_originate_area (lsa, area); |
361 | } | |
362 | ||
363 | void | |
364 | ospf6_abr_range_update (struct ospf6_route *range) | |
365 | { | |
366 | u_int32_t cost = 0; | |
367 | struct ospf6_route *ro; | |
368 | ||
369 | assert (range->type == OSPF6_DEST_TYPE_RANGE); | |
370 | ||
371 | /* update range's cost and active flag */ | |
372 | for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table); | |
373 | ro; ro = ospf6_route_match_next (&range->prefix, ro)) | |
374 | { | |
375 | if (ro->path.area_id == range->path.area_id && | |
376 | ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE)) | |
377 | cost = MAX (cost, ro->path.cost); | |
378 | } | |
379 | ||
380 | if (range->path.cost != cost) | |
381 | { | |
382 | range->path.cost = cost; | |
383 | ||
384 | if (range->path.cost) | |
385 | SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); | |
386 | else | |
387 | UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); | |
388 | ||
389 | ospf6_abr_originate_summary (range); | |
390 | } | |
049207c3 | 391 | } |
392 | ||
393 | void | |
6452df09 | 394 | ospf6_abr_originate_summary (struct ospf6_route *route) |
049207c3 | 395 | { |
396 | listnode node; | |
397 | struct ospf6_area *oa; | |
6452df09 | 398 | struct ospf6_route *range = NULL; |
049207c3 | 399 | |
6452df09 | 400 | if (route->type == OSPF6_DEST_TYPE_NETWORK) |
401 | { | |
402 | oa = ospf6_area_lookup (route->path.area_id, ospf6); | |
403 | range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table); | |
404 | if (range) | |
405 | ospf6_abr_range_update (range); | |
406 | } | |
407 | ||
408 | for (node = listhead (ospf6->area_list); node; nextnode (node)) | |
049207c3 | 409 | { |
410 | oa = (struct ospf6_area *) getdata (node); | |
6452df09 | 411 | ospf6_abr_originate_summary_to_area (route, oa); |
049207c3 | 412 | } |
413 | } | |
414 | ||
415 | /* RFC 2328 16.2. Calculating the inter-area routes */ | |
416 | void | |
417 | ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) | |
418 | { | |
419 | struct prefix prefix, abr_prefix; | |
420 | struct ospf6_route_table *table = NULL; | |
421 | struct ospf6_route *range, *route, *old = NULL; | |
422 | struct ospf6_route *abr_entry; | |
6452df09 | 423 | u_char type = 0; |
049207c3 | 424 | char options[3] = {0, 0, 0}; |
425 | u_int8_t prefix_options = 0; | |
426 | u_int32_t cost = 0; | |
427 | int i; | |
428 | ||
429 | if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) | |
430 | { | |
431 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
432 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
433 | OSPF6_LSA_HEADER_END (lsa->header); | |
434 | prefix.family = AF_INET6; | |
435 | prefix.prefixlen = prefix_lsa->prefix.prefix_length; | |
436 | ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix); | |
437 | table = oa->ospf6->route_table; | |
438 | type = OSPF6_DEST_TYPE_NETWORK; | |
439 | prefix_options = prefix_lsa->prefix.prefix_options; | |
440 | cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa); | |
441 | } | |
442 | else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) | |
443 | { | |
444 | struct ospf6_inter_router_lsa *router_lsa; | |
445 | router_lsa = (struct ospf6_inter_router_lsa *) | |
446 | OSPF6_LSA_HEADER_END (lsa->header); | |
447 | ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix); | |
448 | table = oa->ospf6->brouter_table; | |
449 | type = OSPF6_DEST_TYPE_ROUTER; | |
450 | options[0] = router_lsa->options[0]; | |
451 | options[1] = router_lsa->options[1]; | |
452 | options[2] = router_lsa->options[2]; | |
453 | cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa); | |
454 | } | |
455 | else | |
456 | assert (0); | |
457 | ||
458 | for (route = ospf6_route_lookup (&prefix, table); | |
459 | route && ospf6_route_is_prefix (&prefix, route); | |
460 | route = ospf6_route_next (route)) | |
461 | { | |
462 | if (route->path.area_id == oa->area_id && | |
463 | route->path.origin.type == lsa->header->type && | |
464 | route->path.origin.id == lsa->header->id && | |
465 | route->path.origin.adv_router == lsa->header->adv_router) | |
466 | old = route; | |
467 | } | |
468 | ||
469 | /* (1) if cost == LSInfinity or if the LSA is MaxAge */ | |
470 | if (cost == LS_INFINITY || OSPF6_LSA_IS_MAXAGE (lsa)) | |
471 | { | |
472 | if (old) | |
473 | ospf6_route_remove (old, oa->ospf6->route_table); | |
474 | return; | |
475 | } | |
476 | ||
477 | /* (2) if the LSA is self-originated, ignore */ | |
478 | if (lsa->header->adv_router == oa->ospf6->router_id) | |
479 | { | |
480 | if (old) | |
481 | ospf6_route_remove (old, oa->ospf6->route_table); | |
482 | return; | |
483 | } | |
484 | ||
485 | /* (3) if the prefix is equal to an active configured address range */ | |
6452df09 | 486 | if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) |
049207c3 | 487 | { |
6452df09 | 488 | range = ospf6_route_lookup (&prefix, oa->range_table); |
489 | if (range) | |
490 | { | |
491 | if (old) | |
492 | ospf6_route_remove (old, oa->ospf6->route_table); | |
493 | return; | |
494 | } | |
049207c3 | 495 | } |
496 | ||
497 | /* (4) if the routing table entry for the ABR does not exist */ | |
498 | ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix); | |
499 | abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table); | |
6452df09 | 500 | if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id || |
501 | ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) | |
049207c3 | 502 | { |
503 | if (old) | |
504 | ospf6_route_remove (old, oa->ospf6->route_table); | |
505 | return; | |
506 | } | |
507 | ||
508 | /* (5),(6),(7) the path preference is handled by the sorting | |
509 | in the routing table. Always install the path by substituting | |
510 | old route (if any). */ | |
511 | if (old) | |
512 | route = old; | |
513 | else | |
514 | route = ospf6_route_create (); | |
515 | ||
516 | route->type = type; | |
517 | route->prefix = prefix; | |
518 | route->path.origin.type = lsa->header->type; | |
519 | route->path.origin.id = lsa->header->id; | |
520 | route->path.origin.adv_router = lsa->header->adv_router; | |
521 | route->path.options[0] = options[0]; | |
522 | route->path.options[1] = options[1]; | |
523 | route->path.options[2] = options[2]; | |
524 | route->path.prefix_options = prefix_options; | |
525 | route->path.area_id = oa->area_id; | |
526 | route->path.type = OSPF6_PATH_TYPE_INTER; | |
527 | route->path.cost = abr_entry->path.cost + cost; | |
528 | for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++) | |
529 | route->nexthop[i] = abr_entry->nexthop[i]; | |
530 | ||
531 | ospf6_route_add (route, table); | |
532 | } | |
533 | ||
049207c3 | 534 | \f |
535 | /* Display functions */ | |
536 | int | |
537 | ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) | |
538 | { | |
539 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
540 | struct in6_addr in6; | |
541 | char buf[64]; | |
542 | ||
543 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
544 | OSPF6_LSA_HEADER_END (lsa->header); | |
545 | ||
546 | vty_out (vty, " Metric: %lu%s", | |
547 | (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL); | |
548 | ||
549 | ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options, | |
550 | buf, sizeof (buf)); | |
551 | vty_out (vty, " Prefix Options: %s%s", buf, VNL); | |
552 | ||
553 | ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix); | |
554 | inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); | |
555 | vty_out (vty, " Prefix: %s/%d%s", buf, | |
556 | prefix_lsa->prefix.prefix_length, VNL); | |
557 | ||
558 | return 0; | |
559 | } | |
560 | ||
561 | int | |
562 | ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) | |
563 | { | |
564 | struct ospf6_inter_router_lsa *router_lsa; | |
565 | char buf[64]; | |
566 | ||
567 | router_lsa = (struct ospf6_inter_router_lsa *) | |
568 | OSPF6_LSA_HEADER_END (lsa->header); | |
569 | ||
570 | ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf)); | |
571 | vty_out (vty, " Options: %s%s", buf, VNL); | |
572 | vty_out (vty, " Metric: %lu%s", | |
573 | (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL); | |
574 | inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); | |
575 | vty_out (vty, " Destination Router ID: %s%s", buf, VNL); | |
576 | ||
577 | return 0; | |
578 | } | |
579 | ||
580 | /* Debug commands */ | |
581 | DEFUN (debug_ospf6_abr, | |
582 | debug_ospf6_abr_cmd, | |
583 | "debug ospf6 abr", | |
584 | DEBUG_STR | |
585 | OSPF6_STR | |
586 | "Debug OSPFv3 ABR function\n" | |
587 | ) | |
588 | { | |
589 | OSPF6_DEBUG_ABR_ON (); | |
590 | return CMD_SUCCESS; | |
591 | } | |
592 | ||
593 | DEFUN (no_debug_ospf6_abr, | |
594 | no_debug_ospf6_abr_cmd, | |
595 | "no debug ospf6 abr", | |
596 | NO_STR | |
597 | DEBUG_STR | |
598 | OSPF6_STR | |
599 | "Debug OSPFv3 ABR function\n" | |
600 | ) | |
601 | { | |
602 | OSPF6_DEBUG_ABR_OFF (); | |
603 | return CMD_SUCCESS; | |
604 | } | |
605 | ||
606 | int | |
607 | config_write_ospf6_debug_abr (struct vty *vty) | |
608 | { | |
609 | if (IS_OSPF6_DEBUG_ABR) | |
610 | vty_out (vty, "debug ospf6 abr%s", VNL); | |
611 | return 0; | |
612 | } | |
613 | ||
614 | void | |
615 | install_element_ospf6_debug_abr () | |
616 | { | |
617 | install_element (ENABLE_NODE, &debug_ospf6_abr_cmd); | |
618 | install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd); | |
619 | install_element (CONFIG_NODE, &debug_ospf6_abr_cmd); | |
620 | install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd); | |
621 | } | |
622 | ||
6452df09 | 623 | struct ospf6_lsa_handler inter_prefix_handler = |
624 | { | |
625 | OSPF6_LSTYPE_INTER_PREFIX, | |
626 | "Inter-Prefix", | |
627 | ospf6_inter_area_prefix_lsa_show | |
628 | }; | |
629 | ||
630 | struct ospf6_lsa_handler inter_router_handler = | |
631 | { | |
632 | OSPF6_LSTYPE_INTER_ROUTER, | |
633 | "Inter-Router", | |
634 | ospf6_inter_area_router_lsa_show | |
635 | }; | |
636 | ||
049207c3 | 637 | void |
638 | ospf6_abr_init () | |
639 | { | |
6452df09 | 640 | ospf6_install_lsa_handler (&inter_prefix_handler); |
641 | ospf6_install_lsa_handler (&inter_router_handler); | |
049207c3 | 642 | } |
643 | ||
644 |