]>
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" | |
3b68735f | 31 | #include "thread.h" |
34956b31 | 32 | #include "plist.h" |
33 | #include "filter.h" | |
049207c3 | 34 | |
35 | #include "ospf6_proto.h" | |
36 | #include "ospf6_route.h" | |
37 | #include "ospf6_lsa.h" | |
38 | #include "ospf6_route.h" | |
39 | #include "ospf6_lsdb.h" | |
6452df09 | 40 | #include "ospf6_message.h" |
c3c0ac83 | 41 | #include "ospf6_zebra.h" |
6452df09 | 42 | |
049207c3 | 43 | #include "ospf6_top.h" |
44 | #include "ospf6_area.h" | |
45 | #include "ospf6_interface.h" | |
6452df09 | 46 | #include "ospf6_neighbor.h" |
47 | ||
6452df09 | 48 | #include "ospf6_flood.h" |
3b68735f | 49 | #include "ospf6_intra.h" |
50 | #include "ospf6_abr.h" | |
049207c3 | 51 | #include "ospf6d.h" |
52 | ||
53 | unsigned char conf_debug_ospf6_abr; | |
54 | ||
6452df09 | 55 | int |
56 | ospf6_is_router_abr (struct ospf6 *o) | |
57 | { | |
52dc7ee6 | 58 | struct listnode *node; |
6452df09 | 59 | struct ospf6_area *oa; |
60 | int area_count = 0; | |
61 | ||
1eb8ef25 | 62 | for (ALL_LIST_ELEMENTS_RO (o->area_list, node, oa)) |
63 | if (IS_AREA_ENABLED (oa)) | |
64 | area_count++; | |
6452df09 | 65 | |
66 | if (area_count > 1) | |
67 | return 1; | |
68 | return 0; | |
69 | } | |
70 | ||
c3c0ac83 DS |
71 | static int |
72 | ospf6_abr_nexthops_belong_to_area (struct ospf6_route *route, | |
73 | struct ospf6_area *area) | |
74 | { | |
75 | struct ospf6_interface *oi; | |
76 | ||
77 | oi = ospf6_interface_lookup_by_ifindex (ospf6_route_get_first_nh_index(route)); | |
78 | if (oi && oi->area && oi->area == area) | |
79 | return 1; | |
80 | else | |
81 | return 0; | |
82 | } | |
83 | ||
84 | static void | |
85 | ospf6_abr_delete_route (struct ospf6_route *range, struct ospf6_route *summary, | |
86 | struct ospf6_route_table *summary_table, | |
87 | struct ospf6_lsa *old) | |
88 | { | |
89 | if (summary) | |
90 | { | |
91 | ospf6_route_remove (summary, summary_table); | |
92 | } | |
93 | ||
94 | if (old) | |
95 | ospf6_lsa_purge (old); | |
96 | } | |
97 | ||
3b68735f | 98 | void |
99 | ospf6_abr_enable_area (struct ospf6_area *area) | |
100 | { | |
101 | struct ospf6_area *oa; | |
102 | struct ospf6_route *ro; | |
1eb8ef25 | 103 | struct listnode *node, *nnode; |
3b68735f | 104 | |
1eb8ef25 | 105 | for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa)) |
3b68735f | 106 | { |
3b68735f | 107 | /* update B bit for each area */ |
108 | OSPF6_ROUTER_LSA_SCHEDULE (oa); | |
109 | ||
110 | /* install other area's configured address range */ | |
111 | if (oa != area) | |
112 | { | |
113 | for (ro = ospf6_route_head (oa->range_table); ro; | |
114 | ro = ospf6_route_next (ro)) | |
4846ef64 | 115 | { |
116 | if (CHECK_FLAG (ro->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) | |
117 | ospf6_abr_originate_summary_to_area (ro, area); | |
118 | } | |
3b68735f | 119 | } |
120 | } | |
121 | ||
122 | /* install calculated routes to border routers */ | |
123 | for (ro = ospf6_route_head (area->ospf6->brouter_table); ro; | |
124 | ro = ospf6_route_next (ro)) | |
125 | ospf6_abr_originate_summary_to_area (ro, area); | |
126 | ||
127 | /* install calculated routes to network (may be rejected by ranges) */ | |
128 | for (ro = ospf6_route_head (area->ospf6->route_table); ro; | |
129 | ro = ospf6_route_next (ro)) | |
130 | ospf6_abr_originate_summary_to_area (ro, area); | |
131 | } | |
132 | ||
133 | void | |
134 | ospf6_abr_disable_area (struct ospf6_area *area) | |
135 | { | |
136 | struct ospf6_area *oa; | |
137 | struct ospf6_route *ro; | |
138 | struct ospf6_lsa *old; | |
1eb8ef25 | 139 | struct listnode *node, *nnode; |
3b68735f | 140 | |
141 | /* Withdraw all summary prefixes previously originated */ | |
142 | for (ro = ospf6_route_head (area->summary_prefix); ro; | |
143 | ro = ospf6_route_next (ro)) | |
144 | { | |
145 | old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, | |
146 | area->ospf6->router_id, area->lsdb); | |
147 | if (old) | |
148 | ospf6_lsa_purge (old); | |
149 | ospf6_route_remove (ro, area->summary_prefix); | |
150 | } | |
151 | ||
152 | /* Withdraw all summary router-routes previously originated */ | |
153 | for (ro = ospf6_route_head (area->summary_router); ro; | |
154 | ro = ospf6_route_next (ro)) | |
155 | { | |
156 | old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id, | |
157 | area->ospf6->router_id, area->lsdb); | |
158 | if (old) | |
159 | ospf6_lsa_purge (old); | |
160 | ospf6_route_remove (ro, area->summary_router); | |
161 | } | |
162 | ||
163 | /* Schedule Router-LSA for each area (ABR status may change) */ | |
1eb8ef25 | 164 | for (ALL_LIST_ELEMENTS (area->ospf6->area_list, node, nnode, oa)) |
165 | /* update B bit for each area */ | |
166 | OSPF6_ROUTER_LSA_SCHEDULE (oa); | |
3b68735f | 167 | } |
168 | ||
049207c3 | 169 | /* RFC 2328 12.4.3. Summary-LSAs */ |
c3c0ac83 | 170 | int |
6452df09 | 171 | ospf6_abr_originate_summary_to_area (struct ospf6_route *route, |
172 | struct ospf6_area *area) | |
049207c3 | 173 | { |
174 | struct ospf6_lsa *lsa, *old = NULL; | |
049207c3 | 175 | struct ospf6_route *summary, *range = NULL; |
176 | struct ospf6_area *route_area; | |
177 | char buffer[OSPF6_MAX_LSASIZE]; | |
178 | struct ospf6_lsa_header *lsa_header; | |
179 | caddr_t p; | |
180 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
6452df09 | 181 | struct ospf6_inter_router_lsa *router_lsa; |
182 | struct ospf6_route_table *summary_table = NULL; | |
183 | u_int16_t type; | |
1e05838a | 184 | char buf[64]; |
185 | int is_debug = 0; | |
6452df09 | 186 | |
c3c0ac83 DS |
187 | /* Only destination type network, range or ASBR are considered */ |
188 | if (route->type != OSPF6_DEST_TYPE_NETWORK && | |
189 | route->type != OSPF6_DEST_TYPE_RANGE && | |
190 | ((route->type != OSPF6_DEST_TYPE_ROUTER) || | |
191 | !CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E))) | |
192 | { | |
193 | if (is_debug) | |
194 | zlog_debug ("Route type is none of network, range nor ASBR, ignore"); | |
195 | return 0; | |
196 | } | |
197 | ||
198 | /* AS External routes are never considered */ | |
199 | if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || | |
200 | route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) | |
201 | { | |
202 | if (is_debug) | |
203 | zlog_debug ("Path type is external, skip"); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | /* do not generate if the path's area is the same as target area */ | |
208 | if (route->path.area_id == area->area_id) | |
209 | { | |
210 | if (is_debug) | |
211 | zlog_debug ("The route is in the area itself, ignore"); | |
212 | return 0; | |
213 | } | |
214 | ||
215 | /* do not generate if the nexthops belongs to the target area */ | |
216 | if (ospf6_abr_nexthops_belong_to_area (route, area)) | |
217 | { | |
218 | if (is_debug) | |
219 | zlog_debug ("The route's nexthop is in the same area, ignore"); | |
220 | return 0; | |
221 | } | |
222 | ||
223 | if (route->type == OSPF6_DEST_TYPE_ROUTER) | |
224 | { | |
225 | if (ADV_ROUTER_IN_PREFIX (&route->prefix) == area->ospf6->router_id) | |
226 | { | |
227 | inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), buf, | |
228 | sizeof (buf)); | |
229 | zlog_debug ("%s: Skipping ASBR announcement for ABR (%s)", __func__, | |
230 | buf); | |
231 | return 0; | |
232 | } | |
233 | } | |
234 | ||
1e05838a | 235 | if (route->type == OSPF6_DEST_TYPE_ROUTER) |
6452df09 | 236 | { |
1e05838a | 237 | if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER)) |
6452df09 | 238 | { |
1e05838a | 239 | is_debug++; |
3b68735f | 240 | inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), |
6452df09 | 241 | buf, sizeof (buf)); |
c6487d61 | 242 | zlog_debug ("Originating summary in area %s for ASBR %s", |
243 | area->name, buf); | |
6452df09 | 244 | } |
1e05838a | 245 | summary_table = area->summary_router; |
246 | } | |
247 | else | |
248 | { | |
249 | if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX)) | |
6452df09 | 250 | { |
1e05838a | 251 | is_debug++; |
6452df09 | 252 | prefix2str (&route->prefix, buf, sizeof (buf)); |
c6487d61 | 253 | zlog_debug ("Originating summary in area %s for %s", |
254 | area->name, buf); | |
6452df09 | 255 | } |
1e05838a | 256 | summary_table = area->summary_prefix; |
6452df09 | 257 | } |
049207c3 | 258 | |
6452df09 | 259 | summary = ospf6_route_lookup (&route->prefix, summary_table); |
049207c3 | 260 | if (summary) |
6452df09 | 261 | old = ospf6_lsdb_lookup (summary->path.origin.type, |
049207c3 | 262 | summary->path.origin.id, |
263 | area->ospf6->router_id, area->lsdb); | |
264 | ||
265 | /* if this route has just removed, remove corresponding LSA */ | |
266 | if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) | |
267 | { | |
1e05838a | 268 | if (is_debug) |
c6487d61 | 269 | zlog_debug ("The route has just removed, purge previous LSA"); |
049207c3 | 270 | |
c3c0ac83 DS |
271 | if (route->type == OSPF6_DEST_TYPE_RANGE) |
272 | { | |
273 | /* Whether the route have active longer prefix */ | |
274 | if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) | |
275 | { | |
276 | if (is_debug) | |
277 | zlog_debug ("The range is not active. withdraw"); | |
278 | ||
279 | ospf6_abr_delete_route (route, summary, summary_table, old); | |
280 | } | |
281 | } | |
282 | else | |
283 | if (old) | |
284 | ospf6_lsa_purge (old); | |
049207c3 | 285 | |
c3c0ac83 | 286 | return 0; |
049207c3 | 287 | } |
288 | ||
c3c0ac83 | 289 | if ((route->type == OSPF6_DEST_TYPE_ROUTER) && IS_AREA_STUB(area)) |
049207c3 | 290 | { |
1e05838a | 291 | if (is_debug) |
c3c0ac83 | 292 | zlog_debug ("Area has been stubbed, purge Inter-Router LSA"); |
049207c3 | 293 | |
c3c0ac83 DS |
294 | ospf6_abr_delete_route (route, summary, summary_table, old); |
295 | return 0; | |
049207c3 | 296 | } |
297 | ||
6452df09 | 298 | /* do not generate if the route cost is greater or equal to LSInfinity */ |
8551e6da | 299 | if (route->path.cost >= OSPF_LS_INFINITY) |
049207c3 | 300 | { |
c3c0ac83 DS |
301 | /* When we're clearing the range route because all active prefixes |
302 | * under the range are gone, we set the range's cost to | |
303 | * OSPF_AREA_RANGE_COST_UNSPEC, which is > OSPF_LS_INFINITY. We | |
304 | * don't want to trigger the code here for that. This code is for | |
305 | * handling routes that have gone to infinity. The range removal happens | |
306 | * elsewhere. | |
307 | */ | |
308 | if ((route->type != OSPF6_DEST_TYPE_RANGE) && | |
309 | (route->path.cost != OSPF_AREA_RANGE_COST_UNSPEC)) | |
310 | { | |
311 | if (is_debug) | |
312 | zlog_debug ("The cost exceeds LSInfinity, withdraw"); | |
313 | if (old) | |
314 | ospf6_lsa_purge (old); | |
315 | return 0; | |
316 | } | |
049207c3 | 317 | } |
318 | ||
6452df09 | 319 | /* if this is a route to ASBR */ |
320 | if (route->type == OSPF6_DEST_TYPE_ROUTER) | |
049207c3 | 321 | { |
6452df09 | 322 | /* Only the prefered best path is considered */ |
323 | if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST)) | |
324 | { | |
1e05838a | 325 | if (is_debug) |
c6487d61 | 326 | zlog_debug ("This is the secondary path to the ASBR, ignore"); |
c3c0ac83 DS |
327 | ospf6_abr_delete_route (route, summary, summary_table, old); |
328 | return 0; | |
6452df09 | 329 | } |
330 | ||
331 | /* Do not generate if the area is stub */ | |
332 | /* XXX */ | |
049207c3 | 333 | } |
334 | ||
6452df09 | 335 | /* if this is an intra-area route, this may be suppressed by aggregation */ |
336 | if (route->type == OSPF6_DEST_TYPE_NETWORK && | |
337 | route->path.type == OSPF6_PATH_TYPE_INTRA) | |
049207c3 | 338 | { |
6452df09 | 339 | /* search for configured address range for the route's area */ |
340 | route_area = ospf6_area_lookup (route->path.area_id, area->ospf6); | |
341 | assert (route_area); | |
342 | range = ospf6_route_lookup_bestmatch (&route->prefix, | |
343 | route_area->range_table); | |
344 | ||
345 | /* ranges are ignored when originate backbone routes to transit area. | |
346 | Otherwise, if ranges are configured, the route is suppressed. */ | |
347 | if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) && | |
8551e6da | 348 | (route->path.area_id != OSPF_AREA_BACKBONE || |
6452df09 | 349 | ! IS_AREA_TRANSIT (area))) |
350 | { | |
1e05838a | 351 | if (is_debug) |
6452df09 | 352 | { |
6452df09 | 353 | prefix2str (&range->prefix, buf, sizeof (buf)); |
c6487d61 | 354 | zlog_debug ("Suppressed by range %s of area %s", |
6452df09 | 355 | buf, route_area->name); |
356 | } | |
c3c0ac83 DS |
357 | ospf6_abr_delete_route (route, summary, summary_table, old); |
358 | return 0; | |
6452df09 | 359 | } |
360 | } | |
361 | ||
362 | /* If this is a configured address range */ | |
363 | if (route->type == OSPF6_DEST_TYPE_RANGE) | |
364 | { | |
365 | /* If DoNotAdvertise is set */ | |
366 | if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) | |
367 | { | |
1e05838a | 368 | if (is_debug) |
c6487d61 | 369 | zlog_debug ("This is the range with DoNotAdvertise set. ignore"); |
c3c0ac83 DS |
370 | ospf6_abr_delete_route (route, summary, summary_table, old); |
371 | return 0; | |
6452df09 | 372 | } |
373 | ||
c3c0ac83 | 374 | /* If there are no active prefixes in this range, remove */ |
6452df09 | 375 | if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) |
376 | { | |
1e05838a | 377 | if (is_debug) |
c6487d61 | 378 | zlog_debug ("The range is not active. withdraw"); |
c3c0ac83 DS |
379 | ospf6_abr_delete_route (route, summary, summary_table, old); |
380 | return 0; | |
6452df09 | 381 | } |
049207c3 | 382 | } |
383 | ||
34956b31 | 384 | /* Check export list */ |
385 | if (EXPORT_NAME (area)) | |
386 | { | |
387 | if (EXPORT_LIST (area) == NULL) | |
388 | EXPORT_LIST (area) = | |
389 | access_list_lookup (AFI_IP6, EXPORT_NAME (area)); | |
390 | ||
391 | if (EXPORT_LIST (area)) | |
392 | if (access_list_apply (EXPORT_LIST (area), | |
393 | &route->prefix) == FILTER_DENY) | |
394 | { | |
395 | if (is_debug) | |
396 | { | |
397 | inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), | |
398 | buf, sizeof(buf)); | |
399 | zlog_debug ("prefix %s was denied by export list", buf); | |
400 | } | |
c3c0ac83 | 401 | return 0; |
34956b31 | 402 | } |
403 | } | |
404 | ||
405 | /* Check filter-list */ | |
406 | if (PREFIX_NAME_OUT (area)) | |
407 | { | |
408 | if (PREFIX_LIST_OUT (area) == NULL) | |
409 | PREFIX_LIST_OUT (area) = | |
410 | prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area)); | |
411 | ||
412 | if (PREFIX_LIST_OUT (area)) | |
413 | if (prefix_list_apply (PREFIX_LIST_OUT (area), | |
414 | &route->prefix) != PREFIX_PERMIT) | |
415 | { | |
416 | if (is_debug) | |
417 | { | |
418 | inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)), | |
419 | buf, sizeof (buf)); | |
420 | zlog_debug ("prefix %s was denied by filter-list out", buf); | |
421 | } | |
c3c0ac83 | 422 | return 0; |
34956b31 | 423 | } |
424 | } | |
425 | ||
049207c3 | 426 | /* the route is going to be originated. store it in area's summary_table */ |
427 | if (summary == NULL) | |
428 | { | |
429 | summary = ospf6_route_copy (route); | |
049207c3 | 430 | summary->path.origin.adv_router = area->ospf6->router_id; |
c3c0ac83 DS |
431 | |
432 | if (route->type == OSPF6_DEST_TYPE_ROUTER) | |
433 | { | |
434 | summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER); | |
435 | summary->path.origin.id = ADV_ROUTER_IN_PREFIX (&route->prefix); | |
436 | } | |
437 | else | |
438 | { | |
439 | summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
440 | if (route->type == OSPF6_DEST_TYPE_RANGE) | |
441 | summary->path.origin.id = route->linkstate_id; | |
442 | else | |
443 | summary->path.origin.id = | |
444 | ospf6_new_ls_id (summary->path.origin.type, | |
445 | summary->path.origin.adv_router, area->lsdb); | |
446 | } | |
9428f2dc | 447 | summary = ospf6_route_add (summary, summary_table); |
c3c0ac83 | 448 | |
6452df09 | 449 | } |
450 | else | |
451 | { | |
452 | summary->type = route->type; | |
86f72dcb | 453 | quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed); |
049207c3 | 454 | } |
455 | ||
6452df09 | 456 | summary->path.router_bits = route->path.router_bits; |
457 | summary->path.options[0] = route->path.options[0]; | |
458 | summary->path.options[1] = route->path.options[1]; | |
459 | summary->path.options[2] = route->path.options[2]; | |
460 | summary->path.prefix_options = route->path.prefix_options; | |
461 | summary->path.area_id = area->area_id; | |
462 | summary->path.type = OSPF6_PATH_TYPE_INTER; | |
463 | summary->path.cost = route->path.cost; | |
c3c0ac83 | 464 | /* summary->nexthop[0] = route->nexthop[0]; */ |
6452df09 | 465 | |
049207c3 | 466 | /* prepare buffer */ |
467 | memset (buffer, 0, sizeof (buffer)); | |
468 | lsa_header = (struct ospf6_lsa_header *) buffer; | |
049207c3 | 469 | |
6452df09 | 470 | if (route->type == OSPF6_DEST_TYPE_ROUTER) |
471 | { | |
472 | router_lsa = (struct ospf6_inter_router_lsa *) | |
473 | ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); | |
474 | p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa); | |
475 | ||
476 | /* Fill Inter-Area-Router-LSA */ | |
477 | router_lsa->options[0] = route->path.options[0]; | |
478 | router_lsa->options[1] = route->path.options[1]; | |
479 | router_lsa->options[2] = route->path.options[2]; | |
480 | OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost); | |
3b68735f | 481 | router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix); |
6452df09 | 482 | type = htons (OSPF6_LSTYPE_INTER_ROUTER); |
483 | } | |
484 | else | |
485 | { | |
486 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
487 | ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); | |
488 | p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa); | |
489 | ||
490 | /* Fill Inter-Area-Prefix-LSA */ | |
491 | OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost); | |
492 | prefix_lsa->prefix.prefix_length = route->prefix.prefixlen; | |
493 | prefix_lsa->prefix.prefix_options = route->path.prefix_options; | |
494 | ||
495 | /* set Prefix */ | |
496 | memcpy (p, &route->prefix.u.prefix6, | |
497 | OSPF6_PREFIX_SPACE (route->prefix.prefixlen)); | |
498 | ospf6_prefix_apply_mask (&prefix_lsa->prefix); | |
499 | p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen); | |
500 | type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
501 | } | |
049207c3 | 502 | |
503 | /* Fill LSA Header */ | |
504 | lsa_header->age = 0; | |
6452df09 | 505 | lsa_header->type = type; |
049207c3 | 506 | lsa_header->id = summary->path.origin.id; |
507 | lsa_header->adv_router = area->ospf6->router_id; | |
508 | lsa_header->seqnum = | |
509 | ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id, | |
510 | lsa_header->adv_router, area->lsdb); | |
511 | lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header); | |
512 | ||
513 | /* LSA checksum */ | |
514 | ospf6_lsa_checksum (lsa_header); | |
515 | ||
516 | /* create LSA */ | |
517 | lsa = ospf6_lsa_create (lsa_header); | |
6452df09 | 518 | |
049207c3 | 519 | /* Originate */ |
6452df09 | 520 | ospf6_lsa_originate_area (lsa, area); |
c3c0ac83 DS |
521 | |
522 | return 1; | |
6452df09 | 523 | } |
524 | ||
c3c0ac83 | 525 | void |
6452df09 | 526 | ospf6_abr_range_update (struct ospf6_route *range) |
527 | { | |
528 | u_int32_t cost = 0; | |
529 | struct ospf6_route *ro; | |
c3c0ac83 DS |
530 | int gen_range_summary = 0; |
531 | char buf[INET6_ADDRSTRLEN]; | |
6452df09 | 532 | |
533 | assert (range->type == OSPF6_DEST_TYPE_RANGE); | |
c3c0ac83 | 534 | prefix2str (&range->prefix, buf, sizeof (buf)); |
6452df09 | 535 | |
c3c0ac83 | 536 | if (CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) |
6452df09 | 537 | { |
c3c0ac83 DS |
538 | UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); |
539 | gen_range_summary = 1; | |
6452df09 | 540 | } |
c3c0ac83 | 541 | else |
6452df09 | 542 | { |
c3c0ac83 DS |
543 | /* update range's cost and active flag */ |
544 | for (ro = ospf6_route_match_head (&range->prefix, ospf6->route_table); | |
545 | ro; ro = ospf6_route_match_next (&range->prefix, ro)) | |
546 | { | |
547 | if (ro->path.area_id == range->path.area_id && | |
548 | (ro->path.type == OSPF6_PATH_TYPE_INTRA) && | |
549 | ! CHECK_FLAG (ro->flag, OSPF6_ROUTE_REMOVE)) | |
550 | cost = MAX (cost, ro->path.cost); | |
551 | } | |
552 | } | |
6452df09 | 553 | |
c3c0ac83 DS |
554 | /* Non-zero cost is a proxy for active longer prefixes in this range. |
555 | * If there are active routes covered by this range AND either the configured | |
556 | * cost has changed or the summarized cost has changed then redo summaries. | |
557 | * Alternately, if there are no longer active prefixes and there are | |
558 | * summary announcements, withdraw those announcements. | |
559 | * | |
560 | * The don't advertise code relies on the path.cost being set to UNSPEC to | |
561 | * work the first time. Subsequent times the path.cost is not 0 anyway if there | |
562 | * were active ranges. | |
563 | */ | |
564 | if (CHECK_FLAG (range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) | |
565 | { | |
566 | if (range->path.cost != 0) | |
567 | { | |
568 | range->path.cost = 0; | |
569 | gen_range_summary = 1; | |
570 | } | |
571 | } | |
572 | else if (cost && | |
573 | (((range->path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC) && | |
574 | (range->path.cost != range->path.u.cost_config)) || | |
575 | ((range->path.u.cost_config == OSPF_AREA_RANGE_COST_UNSPEC) && | |
576 | (range->path.cost != cost)))) | |
577 | { | |
578 | if (range->path.u.cost_config == OSPF_AREA_RANGE_COST_UNSPEC) | |
579 | { | |
580 | range->path.cost = cost; | |
581 | } | |
6452df09 | 582 | else |
c3c0ac83 DS |
583 | { |
584 | range->path.cost = range->path.u.cost_config; | |
585 | } | |
6452df09 | 586 | |
c3c0ac83 DS |
587 | SET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); |
588 | gen_range_summary = 1; | |
589 | } | |
590 | else if (!cost && CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) | |
591 | { | |
592 | UNSET_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY); | |
593 | range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; | |
594 | gen_range_summary = 1; | |
595 | } | |
596 | ||
597 | if (gen_range_summary) | |
598 | { | |
6452df09 | 599 | ospf6_abr_originate_summary (range); |
c3c0ac83 DS |
600 | |
601 | if (CHECK_FLAG (range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)) | |
602 | { | |
603 | if (IS_OSPF6_DEBUG_ABR) | |
604 | zlog_debug ("Add discard route"); | |
605 | ||
606 | ospf6_zebra_add_discard (range); | |
607 | } | |
608 | else | |
609 | { | |
610 | if (IS_OSPF6_DEBUG_ABR) | |
611 | zlog_debug ("Delete discard route"); | |
612 | ||
613 | ospf6_zebra_delete_discard (range); | |
614 | } | |
6452df09 | 615 | } |
049207c3 | 616 | } |
617 | ||
618 | void | |
6452df09 | 619 | ospf6_abr_originate_summary (struct ospf6_route *route) |
049207c3 | 620 | { |
1eb8ef25 | 621 | struct listnode *node, *nnode; |
049207c3 | 622 | struct ospf6_area *oa; |
6452df09 | 623 | struct ospf6_route *range = NULL; |
049207c3 | 624 | |
6452df09 | 625 | if (route->type == OSPF6_DEST_TYPE_NETWORK) |
626 | { | |
627 | oa = ospf6_area_lookup (route->path.area_id, ospf6); | |
628 | range = ospf6_route_lookup_bestmatch (&route->prefix, oa->range_table); | |
629 | if (range) | |
c3c0ac83 DS |
630 | { |
631 | ospf6_abr_range_update (range); | |
632 | } | |
6452df09 | 633 | } |
634 | ||
1eb8ef25 | 635 | for (ALL_LIST_ELEMENTS (ospf6->area_list, node, nnode, oa)) |
636 | ospf6_abr_originate_summary_to_area (route, oa); | |
049207c3 | 637 | } |
638 | ||
639 | /* RFC 2328 16.2. Calculating the inter-area routes */ | |
640 | void | |
641 | ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa) | |
642 | { | |
643 | struct prefix prefix, abr_prefix; | |
644 | struct ospf6_route_table *table = NULL; | |
645 | struct ospf6_route *range, *route, *old = NULL; | |
646 | struct ospf6_route *abr_entry; | |
6452df09 | 647 | u_char type = 0; |
049207c3 | 648 | char options[3] = {0, 0, 0}; |
649 | u_int8_t prefix_options = 0; | |
650 | u_int32_t cost = 0; | |
63069ad6 | 651 | u_char router_bits = 0; |
ccb59b11 | 652 | char buf[64]; |
1e05838a | 653 | int is_debug = 0; |
01879114 DD |
654 | struct ospf6_inter_prefix_lsa *prefix_lsa = NULL; |
655 | struct ospf6_inter_router_lsa *router_lsa = NULL; | |
3b68735f | 656 | |
cf1ce250 PJ |
657 | memset (&prefix, 0, sizeof (prefix)); |
658 | ||
049207c3 | 659 | if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) |
660 | { | |
1e05838a | 661 | if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX)) |
662 | { | |
663 | is_debug++; | |
c6487d61 | 664 | zlog_debug ("Examin %s in area %s", lsa->name, oa->name); |
1e05838a | 665 | } |
666 | ||
049207c3 | 667 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) |
668 | OSPF6_LSA_HEADER_END (lsa->header); | |
669 | prefix.family = AF_INET6; | |
670 | prefix.prefixlen = prefix_lsa->prefix.prefix_length; | |
671 | ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix); | |
d91f35bc DO |
672 | if (is_debug) |
673 | prefix2str (&prefix, buf, sizeof (buf)); | |
049207c3 | 674 | table = oa->ospf6->route_table; |
675 | type = OSPF6_DEST_TYPE_NETWORK; | |
676 | prefix_options = prefix_lsa->prefix.prefix_options; | |
677 | cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa); | |
678 | } | |
679 | else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) | |
680 | { | |
1e05838a | 681 | if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER)) |
682 | { | |
683 | is_debug++; | |
c6487d61 | 684 | zlog_debug ("Examin %s in area %s", lsa->name, oa->name); |
1e05838a | 685 | } |
686 | ||
049207c3 | 687 | router_lsa = (struct ospf6_inter_router_lsa *) |
688 | OSPF6_LSA_HEADER_END (lsa->header); | |
689 | ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix); | |
d91f35bc DO |
690 | if (is_debug) |
691 | inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); | |
c3c0ac83 | 692 | |
049207c3 | 693 | table = oa->ospf6->brouter_table; |
694 | type = OSPF6_DEST_TYPE_ROUTER; | |
695 | options[0] = router_lsa->options[0]; | |
696 | options[1] = router_lsa->options[1]; | |
697 | options[2] = router_lsa->options[2]; | |
698 | cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa); | |
63069ad6 | 699 | SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E); |
049207c3 | 700 | } |
701 | else | |
702 | assert (0); | |
703 | ||
ccb59b11 | 704 | /* Find existing route */ |
705 | route = ospf6_route_lookup (&prefix, table); | |
706 | if (route) | |
707 | ospf6_route_lock (route); | |
708 | while (route && ospf6_route_is_prefix (&prefix, route)) | |
049207c3 | 709 | { |
710 | if (route->path.area_id == oa->area_id && | |
711 | route->path.origin.type == lsa->header->type && | |
712 | route->path.origin.id == lsa->header->id && | |
cf1ce250 PJ |
713 | route->path.origin.adv_router == lsa->header->adv_router && |
714 | ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED)) | |
049207c3 | 715 | old = route; |
ccb59b11 | 716 | route = ospf6_route_next (route); |
049207c3 | 717 | } |
c3c0ac83 DS |
718 | if (route) |
719 | ospf6_route_unlock (route); | |
049207c3 | 720 | |
721 | /* (1) if cost == LSInfinity or if the LSA is MaxAge */ | |
8551e6da | 722 | if (cost == OSPF_LS_INFINITY) |
049207c3 | 723 | { |
1e05838a | 724 | if (is_debug) |
c6487d61 | 725 | zlog_debug ("cost is LS_INFINITY, ignore"); |
3b68735f | 726 | if (old) |
63069ad6 | 727 | ospf6_route_remove (old, table); |
3b68735f | 728 | return; |
729 | } | |
730 | if (OSPF6_LSA_IS_MAXAGE (lsa)) | |
731 | { | |
1e05838a | 732 | if (is_debug) |
c6487d61 | 733 | zlog_debug ("LSA is MaxAge, ignore"); |
049207c3 | 734 | if (old) |
63069ad6 | 735 | ospf6_route_remove (old, table); |
049207c3 | 736 | return; |
737 | } | |
738 | ||
739 | /* (2) if the LSA is self-originated, ignore */ | |
740 | if (lsa->header->adv_router == oa->ospf6->router_id) | |
741 | { | |
1e05838a | 742 | if (is_debug) |
c6487d61 | 743 | zlog_debug ("LSA is self-originated, ignore"); |
049207c3 | 744 | if (old) |
63069ad6 | 745 | ospf6_route_remove (old, table); |
049207c3 | 746 | return; |
747 | } | |
748 | ||
749 | /* (3) if the prefix is equal to an active configured address range */ | |
01879114 | 750 | /* or if the NU bit is set in the prefix */ |
6452df09 | 751 | if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX)) |
049207c3 | 752 | { |
6452df09 | 753 | range = ospf6_route_lookup (&prefix, oa->range_table); |
754 | if (range) | |
755 | { | |
1e05838a | 756 | if (is_debug) |
c6487d61 | 757 | zlog_debug ("Prefix is equal to address range, ignore"); |
6452df09 | 758 | if (old) |
63069ad6 | 759 | ospf6_route_remove (old, table); |
6452df09 | 760 | return; |
761 | } | |
01879114 DD |
762 | |
763 | if (CHECK_FLAG (prefix_lsa->prefix.prefix_options, | |
764 | OSPF6_PREFIX_OPTION_NU) || | |
765 | CHECK_FLAG (prefix_lsa->prefix.prefix_options, | |
766 | OSPF6_PREFIX_OPTION_LA)) | |
767 | { | |
768 | if (is_debug) | |
769 | zlog_debug ("Prefix has NU/LA bit set, ignore"); | |
770 | if (old) | |
771 | ospf6_route_remove (old, table); | |
772 | return; | |
773 | } | |
774 | } | |
775 | ||
776 | if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER)) | |
777 | { | |
778 | /* To pass test suites */ | |
779 | if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) || | |
780 | ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6)) | |
781 | { | |
782 | if (is_debug) | |
783 | zlog_debug ("Prefix has NU/LA bit set, ignore"); | |
784 | if (old) | |
785 | ospf6_route_remove (old, table); | |
c3c0ac83 | 786 | |
01879114 DD |
787 | return; |
788 | } | |
c3c0ac83 DS |
789 | /* Avoid infinite recursion if someone has maliciously announced an |
790 | Inter-Router LSA for an ABR | |
791 | */ | |
792 | if (lsa->header->adv_router == router_lsa->router_id) | |
793 | { | |
794 | if (is_debug) | |
795 | zlog_debug ("Ignorning Inter-Router LSA for an ABR (%s)", | |
796 | buf); | |
797 | if (old) | |
798 | ospf6_route_remove (old, table); | |
799 | ||
800 | return; | |
801 | } | |
049207c3 | 802 | } |
803 | ||
804 | /* (4) if the routing table entry for the ABR does not exist */ | |
805 | ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix); | |
806 | abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table); | |
6452df09 | 807 | if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id || |
ccb59b11 | 808 | CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) || |
6452df09 | 809 | ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) |
049207c3 | 810 | { |
1e05838a | 811 | if (is_debug) |
c6487d61 | 812 | zlog_debug ("ABR router entry does not exist, ignore"); |
049207c3 | 813 | if (old) |
63069ad6 | 814 | ospf6_route_remove (old, table); |
049207c3 | 815 | return; |
816 | } | |
817 | ||
34956b31 | 818 | /* Check import list */ |
819 | if (IMPORT_NAME (oa)) | |
820 | { | |
821 | if (IMPORT_LIST (oa) == NULL) | |
822 | IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa)); | |
823 | ||
824 | if (IMPORT_LIST (oa)) | |
825 | if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY) | |
826 | { | |
827 | if (is_debug) | |
828 | zlog_debug ("Prefix was denied by import-list"); | |
829 | if (old) | |
830 | ospf6_route_remove (old, table); | |
831 | return; | |
832 | } | |
833 | } | |
834 | ||
835 | /* Check input prefix-list */ | |
836 | if (PREFIX_NAME_IN (oa)) | |
837 | { | |
838 | if (PREFIX_LIST_IN (oa) == NULL) | |
839 | PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa)); | |
840 | ||
841 | if (PREFIX_LIST_IN (oa)) | |
842 | if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT) | |
843 | { | |
844 | if (is_debug) | |
845 | zlog_debug ("Prefix was denied by prefix-list"); | |
846 | if (old) | |
847 | ospf6_route_remove (old, table); | |
848 | return; | |
849 | } | |
850 | } | |
851 | ||
c3c0ac83 | 852 | /* (5),(6): the path preference is handled by the sorting |
049207c3 | 853 | in the routing table. Always install the path by substituting |
854 | old route (if any). */ | |
855 | if (old) | |
ccb59b11 | 856 | route = ospf6_route_copy (old); |
049207c3 | 857 | else |
858 | route = ospf6_route_create (); | |
859 | ||
860 | route->type = type; | |
861 | route->prefix = prefix; | |
862 | route->path.origin.type = lsa->header->type; | |
863 | route->path.origin.id = lsa->header->id; | |
864 | route->path.origin.adv_router = lsa->header->adv_router; | |
63069ad6 | 865 | route->path.router_bits = router_bits; |
049207c3 | 866 | route->path.options[0] = options[0]; |
867 | route->path.options[1] = options[1]; | |
868 | route->path.options[2] = options[2]; | |
869 | route->path.prefix_options = prefix_options; | |
870 | route->path.area_id = oa->area_id; | |
871 | route->path.type = OSPF6_PATH_TYPE_INTER; | |
872 | route->path.cost = abr_entry->path.cost + cost; | |
049207c3 | 873 | |
c3c0ac83 DS |
874 | ospf6_route_copy_nexthops (route, abr_entry); |
875 | ||
876 | /* (7) If the routes are identical, copy the next hops over to existing | |
877 | route. ospf6's route table implementation will otherwise string both | |
878 | routes, but keep the older one as the best route since the routes | |
879 | are identical. | |
880 | */ | |
881 | old = ospf6_route_lookup (&prefix, table); | |
882 | ||
883 | if (old && (ospf6_route_cmp (route, old) == 0)) | |
884 | { | |
885 | ospf6_route_merge_nexthops (old, route); | |
886 | /* Update RIB/FIB */ | |
887 | if (table->hook_add) | |
888 | (*table->hook_add) (old); | |
889 | ||
890 | /* Delete new route */ | |
891 | ospf6_route_delete (route); | |
892 | } | |
893 | else | |
894 | { | |
895 | if (is_debug) | |
896 | zlog_debug ("Install route: %s", buf); | |
897 | /* ospf6_ia_add_nw_route (table, &prefix, route); */ | |
898 | ospf6_route_add (route, table); | |
899 | } | |
049207c3 | 900 | } |
901 | ||
ccb59b11 | 902 | void |
903 | ospf6_abr_examin_brouter (u_int32_t router_id) | |
904 | { | |
905 | struct ospf6_lsa *lsa; | |
906 | struct ospf6_area *oa; | |
ccb59b11 | 907 | u_int16_t type; |
908 | ||
c3c0ac83 DS |
909 | if (ospf6_is_router_abr (ospf6)) |
910 | oa = ospf6->backbone; | |
911 | else | |
912 | oa = listgetdata(listhead(ospf6->area_list)); | |
ccb59b11 | 913 | |
c3c0ac83 DS |
914 | type = htons (OSPF6_LSTYPE_INTER_ROUTER); |
915 | for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa; | |
916 | lsa = ospf6_lsdb_type_router_next (type, router_id, lsa)) | |
917 | ospf6_abr_examin_summary (lsa, oa); | |
918 | ||
919 | type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
920 | for (lsa = ospf6_lsdb_type_router_head (type, router_id, oa->lsdb); lsa; | |
921 | lsa = ospf6_lsdb_type_router_next (type, router_id, lsa)) | |
922 | ospf6_abr_examin_summary (lsa, oa); | |
ccb59b11 | 923 | } |
924 | ||
34956b31 | 925 | void |
926 | ospf6_abr_reimport (struct ospf6_area *oa) | |
927 | { | |
928 | struct ospf6_lsa *lsa; | |
929 | u_int16_t type; | |
930 | ||
931 | type = htons (OSPF6_LSTYPE_INTER_ROUTER); | |
932 | for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa; | |
933 | lsa = ospf6_lsdb_type_next (type, lsa)) | |
934 | ospf6_abr_examin_summary (lsa, oa); | |
935 | ||
936 | type = htons (OSPF6_LSTYPE_INTER_PREFIX); | |
937 | for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa; | |
938 | lsa = ospf6_lsdb_type_next (type, lsa)) | |
939 | ospf6_abr_examin_summary (lsa, oa); | |
940 | } | |
941 | ||
942 | ||
6b0655a2 | 943 | |
049207c3 | 944 | /* Display functions */ |
e68a6767 DD |
945 | static char * |
946 | ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, | |
947 | int buflen, int pos) | |
948 | { | |
949 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
950 | struct in6_addr in6; | |
951 | ||
952 | if (lsa != NULL) | |
953 | { | |
954 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
955 | OSPF6_LSA_HEADER_END (lsa->header); | |
956 | ||
957 | ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix); | |
958 | if (buf) | |
959 | { | |
960 | inet_ntop (AF_INET6, &in6, buf, buflen); | |
961 | sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length); | |
962 | } | |
963 | } | |
964 | ||
965 | return (buf); | |
966 | } | |
967 | ||
6ac29a51 | 968 | static int |
049207c3 | 969 | ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) |
970 | { | |
971 | struct ospf6_inter_prefix_lsa *prefix_lsa; | |
e68a6767 | 972 | char buf[INET6_ADDRSTRLEN]; |
049207c3 | 973 | |
974 | prefix_lsa = (struct ospf6_inter_prefix_lsa *) | |
975 | OSPF6_LSA_HEADER_END (lsa->header); | |
976 | ||
977 | vty_out (vty, " Metric: %lu%s", | |
978 | (u_long) OSPF6_ABR_SUMMARY_METRIC (prefix_lsa), VNL); | |
979 | ||
980 | ospf6_prefix_options_printbuf (prefix_lsa->prefix.prefix_options, | |
981 | buf, sizeof (buf)); | |
982 | vty_out (vty, " Prefix Options: %s%s", buf, VNL); | |
983 | ||
e68a6767 DD |
984 | vty_out (vty, " Prefix: %s%s", |
985 | ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf), | |
986 | 0), VNL); | |
049207c3 | 987 | |
988 | return 0; | |
989 | } | |
990 | ||
e68a6767 DD |
991 | static char * |
992 | ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, | |
993 | int buflen, int pos) | |
994 | { | |
995 | struct ospf6_inter_router_lsa *router_lsa; | |
996 | ||
997 | if (lsa != NULL) | |
998 | { | |
999 | router_lsa = (struct ospf6_inter_router_lsa *) | |
1000 | OSPF6_LSA_HEADER_END (lsa->header); | |
1001 | ||
1002 | ||
1003 | if (buf) | |
1004 | inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen); | |
1005 | } | |
1006 | ||
1007 | return (buf); | |
1008 | } | |
1009 | ||
6ac29a51 | 1010 | static int |
049207c3 | 1011 | ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) |
1012 | { | |
1013 | struct ospf6_inter_router_lsa *router_lsa; | |
1014 | char buf[64]; | |
1015 | ||
1016 | router_lsa = (struct ospf6_inter_router_lsa *) | |
1017 | OSPF6_LSA_HEADER_END (lsa->header); | |
1018 | ||
1019 | ospf6_options_printbuf (router_lsa->options, buf, sizeof (buf)); | |
1020 | vty_out (vty, " Options: %s%s", buf, VNL); | |
1021 | vty_out (vty, " Metric: %lu%s", | |
1022 | (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL); | |
e68a6767 | 1023 | |
049207c3 | 1024 | inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf)); |
1025 | vty_out (vty, " Destination Router ID: %s%s", buf, VNL); | |
1026 | ||
1027 | return 0; | |
1028 | } | |
1029 | ||
1030 | /* Debug commands */ | |
1031 | DEFUN (debug_ospf6_abr, | |
1032 | debug_ospf6_abr_cmd, | |
1033 | "debug ospf6 abr", | |
1034 | DEBUG_STR | |
1035 | OSPF6_STR | |
1036 | "Debug OSPFv3 ABR function\n" | |
1037 | ) | |
1038 | { | |
1039 | OSPF6_DEBUG_ABR_ON (); | |
1040 | return CMD_SUCCESS; | |
1041 | } | |
1042 | ||
1043 | DEFUN (no_debug_ospf6_abr, | |
1044 | no_debug_ospf6_abr_cmd, | |
1045 | "no debug ospf6 abr", | |
1046 | NO_STR | |
1047 | DEBUG_STR | |
1048 | OSPF6_STR | |
1049 | "Debug OSPFv3 ABR function\n" | |
1050 | ) | |
1051 | { | |
1052 | OSPF6_DEBUG_ABR_OFF (); | |
1053 | return CMD_SUCCESS; | |
1054 | } | |
1055 | ||
1056 | int | |
1057 | config_write_ospf6_debug_abr (struct vty *vty) | |
1058 | { | |
1059 | if (IS_OSPF6_DEBUG_ABR) | |
1060 | vty_out (vty, "debug ospf6 abr%s", VNL); | |
1061 | return 0; | |
1062 | } | |
1063 | ||
1064 | void | |
6ac29a51 | 1065 | install_element_ospf6_debug_abr (void) |
049207c3 | 1066 | { |
1067 | install_element (ENABLE_NODE, &debug_ospf6_abr_cmd); | |
1068 | install_element (ENABLE_NODE, &no_debug_ospf6_abr_cmd); | |
1069 | install_element (CONFIG_NODE, &debug_ospf6_abr_cmd); | |
1070 | install_element (CONFIG_NODE, &no_debug_ospf6_abr_cmd); | |
1071 | } | |
1072 | ||
6452df09 | 1073 | struct ospf6_lsa_handler inter_prefix_handler = |
1074 | { | |
1075 | OSPF6_LSTYPE_INTER_PREFIX, | |
1076 | "Inter-Prefix", | |
e68a6767 DD |
1077 | "IAP", |
1078 | ospf6_inter_area_prefix_lsa_show, | |
1079 | ospf6_inter_area_prefix_lsa_get_prefix_str, | |
6452df09 | 1080 | }; |
1081 | ||
1082 | struct ospf6_lsa_handler inter_router_handler = | |
1083 | { | |
1084 | OSPF6_LSTYPE_INTER_ROUTER, | |
1085 | "Inter-Router", | |
e68a6767 DD |
1086 | "IAR", |
1087 | ospf6_inter_area_router_lsa_show, | |
1088 | ospf6_inter_area_router_lsa_get_prefix_str, | |
6452df09 | 1089 | }; |
1090 | ||
049207c3 | 1091 | void |
6ac29a51 | 1092 | ospf6_abr_init (void) |
049207c3 | 1093 | { |
6452df09 | 1094 | ospf6_install_lsa_handler (&inter_prefix_handler); |
1095 | ospf6_install_lsa_handler (&inter_router_handler); | |
049207c3 | 1096 | } |
1097 | ||
1098 |