blob: c1c6d359cdc0abf873068cf641afb664e5958f5a [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
24#include "log.h"
25#include "memory.h"
26#include "prefix.h"
27#include "table.h"
28#include "vty.h"
29#include "command.h"
30
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6_proto.h"
32#include "ospf6_lsa.h"
hasso049207c2004-08-04 20:02:13 +000033#include "ospf6_lsdb.h"
hasso508e53e2004-05-18 18:57:06 +000034#include "ospf6_route.h"
hasso049207c2004-08-04 20:02:13 +000035#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000036
hasso508e53e2004-05-18 18:57:06 +000037unsigned char conf_debug_ospf6_route = 0;
38
39void
40ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
41 struct prefix *prefix)
paul718e3742002-12-13 20:15:29 +000042{
hasso508e53e2004-05-18 18:57:06 +000043 memset (prefix, 0, sizeof (struct prefix));
44 prefix->family = AF_INET6;
45 prefix->prefixlen = 64;
46 memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
47 memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
paul718e3742002-12-13 20:15:29 +000048}
49
hasso508e53e2004-05-18 18:57:06 +000050void
51ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
paul718e3742002-12-13 20:15:29 +000052{
hasso508e53e2004-05-18 18:57:06 +000053 u_int32_t adv_router, id;
hasso4846ef62004-09-03 06:04:00 +000054 char adv_router_str[16], id_str[16];
hasso508e53e2004-05-18 18:57:06 +000055 memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
56 memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
57 inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
hasso4846ef62004-09-03 06:04:00 +000058 inet_ntop (AF_INET, &id, id_str, sizeof (id_str));
59 if (ntohl (id))
60 snprintf (buf, size, "%s Net-ID: %s", adv_router_str, id_str);
61 else
62 snprintf (buf, size, "%s", adv_router_str);
paul718e3742002-12-13 20:15:29 +000063}
64
hasso508e53e2004-05-18 18:57:06 +000065/* Global strings for logging */
paul0c083ee2004-10-10 12:54:58 +000066const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +000067{ "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
hasso508e53e2004-05-18 18:57:06 +000068
paul0c083ee2004-10-10 12:54:58 +000069const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +000070{ "?", "R", "N", "D", "L", "A", };
hasso508e53e2004-05-18 18:57:06 +000071
paul0c083ee2004-10-10 12:54:58 +000072const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
hasso508e53e2004-05-18 18:57:06 +000073{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
74
paul0c083ee2004-10-10 12:54:58 +000075const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
hasso4846ef62004-09-03 06:04:00 +000076{ "??", "IA", "IE", "E1", "E2", };
hasso508e53e2004-05-18 18:57:06 +000077
78
79struct ospf6_route *
80ospf6_route_create ()
paul718e3742002-12-13 20:15:29 +000081{
hasso508e53e2004-05-18 18:57:06 +000082 struct ospf6_route *route;
83 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
84 return route;
paul718e3742002-12-13 20:15:29 +000085}
86
hasso508e53e2004-05-18 18:57:06 +000087void
88ospf6_route_delete (struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +000089{
hasso508e53e2004-05-18 18:57:06 +000090 XFREE (MTYPE_OSPF6_ROUTE, route);
paul718e3742002-12-13 20:15:29 +000091}
92
hasso508e53e2004-05-18 18:57:06 +000093struct ospf6_route *
94ospf6_route_copy (struct ospf6_route *route)
95{
96 struct ospf6_route *new;
97
98 new = ospf6_route_create ();
99 memcpy (new, route, sizeof (struct ospf6_route));
100 new->rnode = NULL;
101 new->prev = NULL;
102 new->next = NULL;
103 new->lock = 0;
104 return new;
105}
106
107void
108ospf6_route_lock (struct ospf6_route *route)
109{
110 route->lock++;
111}
112
113void
114ospf6_route_unlock (struct ospf6_route *route)
115{
116 assert (route->lock > 0);
117 route->lock--;
118 if (route->lock == 0)
119 ospf6_route_delete (route);
120}
121
122/* Route compare function. If ra is more preferred, it returns
123 less than 0. If rb is more preferred returns greater than 0.
124 Otherwise (neither one is preferred), returns 0 */
125static int
126ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
127{
128 assert (ospf6_route_is_same (ra, rb));
129 assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
130 ra->path.type < OSPF6_PATH_TYPE_MAX);
131 assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
132 rb->path.type < OSPF6_PATH_TYPE_MAX);
133
134 if (ra->type != rb->type)
135 return (ra->type - rb->type);
136
137 if (ra->path.area_id != rb->path.area_id)
138 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
139
140 if (ra->path.type != rb->path.type)
141 return (ra->path.type - rb->path.type);
142
143 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
144 {
145 if (ra->path.cost_e2 != rb->path.cost_e2)
146 return (ra->path.cost_e2 - rb->path.cost_e2);
147 }
148 else
149 {
150 if (ra->path.cost != rb->path.cost)
151 return (ra->path.cost - rb->path.cost);
152 }
153
154 return 0;
155}
156
157struct ospf6_route *
158ospf6_route_lookup (struct prefix *prefix,
paul718e3742002-12-13 20:15:29 +0000159 struct ospf6_route_table *table)
160{
161 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000162 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000163
164 node = route_node_lookup (table->table, prefix);
hasso508e53e2004-05-18 18:57:06 +0000165 if (node == NULL)
166 return NULL;
paul718e3742002-12-13 20:15:29 +0000167
hasso508e53e2004-05-18 18:57:06 +0000168 route = (struct ospf6_route *) node->info;
169 return route;
paul718e3742002-12-13 20:15:29 +0000170}
171
hasso508e53e2004-05-18 18:57:06 +0000172struct ospf6_route *
173ospf6_route_lookup_identical (struct ospf6_route *route,
174 struct ospf6_route_table *table)
175{
176 struct ospf6_route *target;
177
178 for (target = ospf6_route_lookup (&route->prefix, table);
179 target; target = target->next)
180 {
181 if (ospf6_route_is_identical (target, route))
182 return target;
183 }
184 return NULL;
185}
186
187struct ospf6_route *
188ospf6_route_lookup_bestmatch (struct prefix *prefix,
189 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000190{
191 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000192 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000193
hasso508e53e2004-05-18 18:57:06 +0000194 node = route_node_match (table->table, prefix);
195 if (node == NULL)
196 return NULL;
197 route_unlock_node (node);
paul718e3742002-12-13 20:15:29 +0000198
hasso508e53e2004-05-18 18:57:06 +0000199 route = (struct ospf6_route *) node->info;
200 return route;
paul718e3742002-12-13 20:15:29 +0000201}
202
hasso508e53e2004-05-18 18:57:06 +0000203#ifndef NDEBUG
204static void
205_route_count_assert (struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000206{
hasso508e53e2004-05-18 18:57:06 +0000207 struct ospf6_route *debug;
hassoccb59b12004-08-25 09:10:37 +0000208 char buf[64];
paul0c083ee2004-10-10 12:54:58 +0000209 unsigned int num = 0;
hasso508e53e2004-05-18 18:57:06 +0000210 for (debug = ospf6_route_head (table); debug;
211 debug = ospf6_route_next (debug))
212 num++;
hassoccb59b12004-08-25 09:10:37 +0000213
214 if (num == table->count)
215 return;
216
217 zlog_info ("PANIC !! table[%p]->count = %d, real = %d",
218 table, table->count, num);
219 for (debug = ospf6_route_head (table); debug;
220 debug = ospf6_route_next (debug))
221 {
222 prefix2str (&debug->prefix, buf, sizeof (buf));
223 zlog_info ("%p %p %s", debug->prev, debug->next, buf);
224 }
225 zlog_info ("DUMP END");
226
hasso508e53e2004-05-18 18:57:06 +0000227 assert (num == table->count);
paul718e3742002-12-13 20:15:29 +0000228}
hasso508e53e2004-05-18 18:57:06 +0000229#define ospf6_route_count_assert(t) (_route_count_assert (t))
230#else
231#define ospf6_route_count_assert(t) ((void) 0)
232#endif /*NDEBUG*/
paul718e3742002-12-13 20:15:29 +0000233
hasso508e53e2004-05-18 18:57:06 +0000234struct ospf6_route *
235ospf6_route_add (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000236 struct ospf6_route_table *table)
237{
hasso508e53e2004-05-18 18:57:06 +0000238 struct route_node *node, *nextnode, *prevnode;
239 struct ospf6_route *current = NULL;
240 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
241 char buf[64];
242 struct timeval now;
paul718e3742002-12-13 20:15:29 +0000243
hasso508e53e2004-05-18 18:57:06 +0000244 assert (route->rnode == NULL);
245 assert (route->lock == 0);
246 assert (route->next == NULL);
247 assert (route->prev == NULL);
paul718e3742002-12-13 20:15:29 +0000248
hasso508e53e2004-05-18 18:57:06 +0000249 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
250 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
251 else
252 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000253
hasso508e53e2004-05-18 18:57:06 +0000254 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
255 zlog_info ("route add %s", buf);
paul718e3742002-12-13 20:15:29 +0000256
hasso508e53e2004-05-18 18:57:06 +0000257 gettimeofday (&now, NULL);
258
259 node = route_node_get (table->table, &route->prefix);
260 route->rnode = node;
261
262 /* find place to insert */
263 for (current = node->info; current; current = current->next)
paul718e3742002-12-13 20:15:29 +0000264 {
hasso508e53e2004-05-18 18:57:06 +0000265 if (! ospf6_route_is_same (current, route))
266 next = current;
267 else if (current->type != route->type)
268 prev = current;
269 else if (ospf6_route_is_same_origin (current, route))
270 old = current;
271 else if (ospf6_route_cmp (current, route) > 0)
272 next = current;
273 else
274 prev = current;
275
276 if (old || next)
277 break;
paul718e3742002-12-13 20:15:29 +0000278 }
hasso508e53e2004-05-18 18:57:06 +0000279
280 if (old)
281 {
282 /* if route does not actually change, return unchanged */
283 if (ospf6_route_is_identical (old, route))
284 {
285 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
286 zlog_info (" identical route found, ignore");
287
288 ospf6_route_delete (route);
289 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
290 ospf6_route_count_assert (table);
hasso9428f2d2004-09-13 14:01:12 +0000291
hasso508e53e2004-05-18 18:57:06 +0000292 return old;
293 }
294
295 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
296 zlog_info (" old route found, replace");
297
298 /* replace old one if exists */
299 if (node->info == old)
300 {
301 node->info = route;
302 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
303 }
304
305 if (old->prev)
306 old->prev->next = route;
307 route->prev = old->prev;
308 if (old->next)
309 old->next->prev = route;
310 route->next = old->next;
311
312 route->installed = old->installed;
313 route->changed = now;
314
315 ospf6_route_unlock (old); /* will be deleted later */
316 ospf6_route_lock (route);
317
318 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
hasso9428f2d2004-09-13 14:01:12 +0000319 ospf6_route_count_assert (table);
320
hasso508e53e2004-05-18 18:57:06 +0000321 if (table->hook_add)
322 (*table->hook_add) (route);
323
hasso508e53e2004-05-18 18:57:06 +0000324 return route;
325 }
326
327 /* insert if previous or next node found */
328 if (prev || next)
329 {
330 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
331 zlog_info (" another path found, insert");
332
333 if (prev == NULL)
334 prev = next->prev;
335 if (next == NULL)
336 next = prev->next;
337
338 if (prev)
339 prev->next = route;
340 route->prev = prev;
341 if (next)
342 next->prev = route;
343 route->next = next;
344
345 if (node->info == next)
346 {
347 assert (next->rnode == node);
348 node->info = route;
349 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
350 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
351 }
352
353 route->installed = now;
354 route->changed = now;
355
356 ospf6_route_lock (route);
357 table->count++;
hasso9428f2d2004-09-13 14:01:12 +0000358 ospf6_route_count_assert (table);
hasso508e53e2004-05-18 18:57:06 +0000359
360 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
361 if (table->hook_add)
362 (*table->hook_add) (route);
363
hasso508e53e2004-05-18 18:57:06 +0000364 return route;
365 }
366
367 /* Else, this is the brand new route regarding to the prefix */
368 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
369 zlog_info (" brand new route, add");
370
371 assert (node->info == NULL);
372 node->info = route;
373 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
374 ospf6_route_lock (route);
375 route->installed = now;
376 route->changed = now;
377
378 /* lookup real existing next route */
379 nextnode = node;
380 route_lock_node (nextnode);
381 do {
382 nextnode = route_next (nextnode);
383 } while (nextnode && nextnode->info == NULL);
384
385 /* set next link */
386 if (nextnode == NULL)
387 route->next = NULL;
paul718e3742002-12-13 20:15:29 +0000388 else
389 {
hasso508e53e2004-05-18 18:57:06 +0000390 route_unlock_node (nextnode);
391
392 next = nextnode->info;
393 route->next = next;
394 next->prev = route;
paul718e3742002-12-13 20:15:29 +0000395 }
396
hasso508e53e2004-05-18 18:57:06 +0000397 /* lookup real existing prev route */
398 prevnode = node;
399 route_lock_node (prevnode);
400 do {
401 prevnode = route_prev (prevnode);
402 } while (prevnode && prevnode->info == NULL);
paul718e3742002-12-13 20:15:29 +0000403
hasso508e53e2004-05-18 18:57:06 +0000404 /* set prev link */
405 if (prevnode == NULL)
406 route->prev = NULL;
paul718e3742002-12-13 20:15:29 +0000407 else
408 {
hasso508e53e2004-05-18 18:57:06 +0000409 route_unlock_node (prevnode);
410
411 prev = prevnode->info;
412 while (prev->next && ospf6_route_is_same (prev, prev->next))
413 prev = prev->next;
414 route->prev = prev;
415 prev->next = route;
paul718e3742002-12-13 20:15:29 +0000416 }
417
hasso508e53e2004-05-18 18:57:06 +0000418 table->count++;
hasso9428f2d2004-09-13 14:01:12 +0000419 ospf6_route_count_assert (table);
paul718e3742002-12-13 20:15:29 +0000420
hasso508e53e2004-05-18 18:57:06 +0000421 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
422 if (table->hook_add)
423 (*table->hook_add) (route);
paul718e3742002-12-13 20:15:29 +0000424
hasso508e53e2004-05-18 18:57:06 +0000425 return route;
paul718e3742002-12-13 20:15:29 +0000426}
427
428void
hasso508e53e2004-05-18 18:57:06 +0000429ospf6_route_remove (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000430 struct ospf6_route_table *table)
431{
hasso508e53e2004-05-18 18:57:06 +0000432 struct route_node *node;
433 struct ospf6_route *current;
434 char buf[64];
paul718e3742002-12-13 20:15:29 +0000435
hasso508e53e2004-05-18 18:57:06 +0000436 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
437 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
438 else
439 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000440
hasso508e53e2004-05-18 18:57:06 +0000441 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
442 zlog_info ("route remove: %s", buf);
443
444 node = route_node_lookup (table->table, &route->prefix);
445 assert (node);
446
447 /* find the route to remove, making sure that the route pointer
448 is from the route table. */
449 current = node->info;
450 while (current && ospf6_route_is_same (current, route))
paul718e3742002-12-13 20:15:29 +0000451 {
hasso508e53e2004-05-18 18:57:06 +0000452 if (current == route)
453 break;
454 current = current->next;
455 }
456 assert (current == route);
457
458 /* adjust doubly linked list */
459 if (route->prev)
460 route->prev->next = route->next;
461 if (route->next)
462 route->next->prev = route->prev;
463
464 if (node->info == route)
465 {
466 if (route->next && ospf6_route_is_same (route->next, route))
paul718e3742002-12-13 20:15:29 +0000467 {
hasso508e53e2004-05-18 18:57:06 +0000468 node->info = route->next;
469 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
paul718e3742002-12-13 20:15:29 +0000470 }
hasso508e53e2004-05-18 18:57:06 +0000471 else
472 node->info = NULL; /* should unlock route_node here ? */
paul718e3742002-12-13 20:15:29 +0000473 }
474
hasso9428f2d2004-09-13 14:01:12 +0000475 table->count--;
476 ospf6_route_count_assert (table);
477
478 SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
479
paul718e3742002-12-13 20:15:29 +0000480 if (table->hook_remove)
hasso508e53e2004-05-18 18:57:06 +0000481 (*table->hook_remove) (route);
paul718e3742002-12-13 20:15:29 +0000482
hasso508e53e2004-05-18 18:57:06 +0000483 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +0000484}
paul718e3742002-12-13 20:15:29 +0000485
hasso508e53e2004-05-18 18:57:06 +0000486struct ospf6_route *
487ospf6_route_head (struct ospf6_route_table *table)
488{
489 struct route_node *node;
490 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000491
hasso508e53e2004-05-18 18:57:06 +0000492 node = route_top (table->table);
493 if (node == NULL)
494 return NULL;
495
496 /* skip to the real existing entry */
497 while (node && node->info == NULL)
498 node = route_next (node);
499 if (node == NULL)
500 return NULL;
501
502 route_unlock_node (node);
503 assert (node->info);
504
505 route = (struct ospf6_route *) node->info;
506 assert (route->prev == NULL);
507 ospf6_route_lock (route);
508 return route;
509}
510
511struct ospf6_route *
512ospf6_route_next (struct ospf6_route *route)
513{
514 struct ospf6_route *next = route->next;
515
516 ospf6_route_unlock (route);
517 if (next)
518 ospf6_route_lock (next);
519
520 return next;
521}
522
523struct ospf6_route *
524ospf6_route_best_next (struct ospf6_route *route)
525{
526 struct route_node *rnode;
527 struct ospf6_route *next;
528
529 rnode = route->rnode;
530 route_lock_node (rnode);
531 rnode = route_next (rnode);
532 while (rnode && rnode->info == NULL)
533 rnode = route_next (rnode);
534 if (rnode == NULL)
535 return NULL;
536 route_unlock_node (rnode);
537
538 assert (rnode->info);
539 next = (struct ospf6_route *) rnode->info;
540 ospf6_route_unlock (route);
541 ospf6_route_lock (next);
542 return next;
543}
544
545/* Macro version of check_bit (). */
546#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
547
548struct ospf6_route *
549ospf6_route_match_head (struct prefix *prefix,
550 struct ospf6_route_table *table)
551{
552 struct route_node *node;
553 struct ospf6_route *route;
554
555 /* Walk down tree. */
556 node = table->table->top;
557 while (node && node->p.prefixlen < prefix->prefixlen &&
558 prefix_match (&node->p, prefix))
559 node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
560
561 if (node)
562 route_lock_node (node);
563 while (node && node->info == NULL)
564 node = route_next (node);
565 if (node == NULL)
566 return NULL;
567 route_unlock_node (node);
568
569 if (! prefix_match (prefix, &node->p))
570 return NULL;
571
572 route = node->info;
573 ospf6_route_lock (route);
574 return route;
575}
576
577struct ospf6_route *
578ospf6_route_match_next (struct prefix *prefix,
579 struct ospf6_route *route)
580{
581 struct ospf6_route *next;
582
583 next = ospf6_route_next (route);
584 if (next && ! prefix_match (prefix, &next->prefix))
585 {
586 ospf6_route_unlock (next);
587 next = NULL;
588 }
589
590 return next;
paul718e3742002-12-13 20:15:29 +0000591}
592
593void
594ospf6_route_remove_all (struct ospf6_route_table *table)
595{
hasso508e53e2004-05-18 18:57:06 +0000596 struct ospf6_route *route;
597 for (route = ospf6_route_head (table); route;
598 route = ospf6_route_next (route))
599 ospf6_route_remove (route, table);
paul718e3742002-12-13 20:15:29 +0000600}
601
paul718e3742002-12-13 20:15:29 +0000602struct ospf6_route_table *
hasso508e53e2004-05-18 18:57:06 +0000603ospf6_route_table_create ()
paul718e3742002-12-13 20:15:29 +0000604{
paul718e3742002-12-13 20:15:29 +0000605 struct ospf6_route_table *new;
paul718e3742002-12-13 20:15:29 +0000606 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
paul718e3742002-12-13 20:15:29 +0000607 new->table = route_table_init ();
paul718e3742002-12-13 20:15:29 +0000608 return new;
609}
610
611void
612ospf6_route_table_delete (struct ospf6_route_table *table)
613{
paul718e3742002-12-13 20:15:29 +0000614 ospf6_route_remove_all (table);
615 route_table_finish (table->table);
paul718e3742002-12-13 20:15:29 +0000616 XFREE (MTYPE_OSPF6_ROUTE, table);
617}
618
paul718e3742002-12-13 20:15:29 +0000619
620
621/* VTY commands */
hasso508e53e2004-05-18 18:57:06 +0000622void
623ospf6_route_show (struct vty *vty, struct ospf6_route *route)
624{
625 int i;
626 char destination[64], nexthop[64];
627 char duration[16], ifname[IFNAMSIZ];
628 struct timeval now, res;
629
630 gettimeofday (&now, (struct timezone *) NULL);
631 timersub (&now, &route->changed, &res);
632 timerstring (&res, duration, sizeof (duration));
633
634 /* destination */
635 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
636 ospf6_linkstate_prefix2str (&route->prefix, destination,
637 sizeof (destination));
638 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
639 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
640 destination, sizeof (destination));
641 else
642 prefix2str (&route->prefix, destination, sizeof (destination));
643
644 /* nexthop */
645 inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
646 sizeof (nexthop));
647 if (! if_indextoname (route->nexthop[0].ifindex, ifname))
648 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
649
650 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
651 (ospf6_route_is_best (route) ? '*' : ' '),
652 OSPF6_DEST_TYPE_SUBSTR (route->type),
653 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
hasso049207c2004-08-04 20:02:13 +0000654 destination, nexthop, ifname, duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000655
656 for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
657 i < OSPF6_MULTI_PATH_LIMIT; i++)
658 {
659 /* nexthop */
660 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
661 sizeof (nexthop));
662 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
663 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
664
665 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
hasso049207c2004-08-04 20:02:13 +0000666 ' ', "", "", "", nexthop, ifname, "", VNL);
hasso508e53e2004-05-18 18:57:06 +0000667 }
668}
paul718e3742002-12-13 20:15:29 +0000669
670void
hasso508e53e2004-05-18 18:57:06 +0000671ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +0000672{
hasso508e53e2004-05-18 18:57:06 +0000673 char destination[64], nexthop[64], ifname[IFNAMSIZ];
674 char area_id[16], id[16], adv_router[16], capa[16], options[16];
paul718e3742002-12-13 20:15:29 +0000675 struct timeval now, res;
676 char duration[16];
hasso508e53e2004-05-18 18:57:06 +0000677 int i;
paul718e3742002-12-13 20:15:29 +0000678
679 gettimeofday (&now, (struct timezone *) NULL);
680
681 /* destination */
hasso508e53e2004-05-18 18:57:06 +0000682 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
683 ospf6_linkstate_prefix2str (&route->prefix, destination,
684 sizeof (destination));
685 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
686 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
687 destination, sizeof (destination));
paul718e3742002-12-13 20:15:29 +0000688 else
hasso508e53e2004-05-18 18:57:06 +0000689 prefix2str (&route->prefix, destination, sizeof (destination));
hasso049207c2004-08-04 20:02:13 +0000690 vty_out (vty, "Destination: %s%s", destination, VNL);
paul718e3742002-12-13 20:15:29 +0000691
hasso508e53e2004-05-18 18:57:06 +0000692 /* destination type */
693 vty_out (vty, "Destination type: %s%s",
694 OSPF6_DEST_TYPE_NAME (route->type),
hasso049207c2004-08-04 20:02:13 +0000695 VNL);
hasso508e53e2004-05-18 18:57:06 +0000696
697 /* Time */
698 timersub (&now, &route->installed, &res);
699 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000700 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000701
702 timersub (&now, &route->changed, &res);
703 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000704 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000705
706 /* Debugging info */
707 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
708 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
709 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
710 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
711 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
hasso049207c2004-08-04 20:02:13 +0000712 VNL);
hasso508e53e2004-05-18 18:57:06 +0000713 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000714 route->prev, route, route->next, VNL);
hasso508e53e2004-05-18 18:57:06 +0000715
716 /* Path section */
717
718 /* Area-ID */
719 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
hasso049207c2004-08-04 20:02:13 +0000720 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
hasso508e53e2004-05-18 18:57:06 +0000721
722 /* Path type */
723 vty_out (vty, "Path Type: %s%s",
hasso049207c2004-08-04 20:02:13 +0000724 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
hasso508e53e2004-05-18 18:57:06 +0000725
726 /* LS Origin */
727 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
728 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
729 sizeof (adv_router));
730 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
hasso1e058382004-09-01 21:36:14 +0000731 ospf6_lstype_name (route->path.origin.type),
hasso049207c2004-08-04 20:02:13 +0000732 id, adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000733
734 /* Options */
735 ospf6_options_printbuf (route->path.options, options, sizeof (options));
hasso049207c2004-08-04 20:02:13 +0000736 vty_out (vty, "Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000737
738 /* Router Bits */
739 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
hasso049207c2004-08-04 20:02:13 +0000740 vty_out (vty, "Router Bits: %s%s", capa, VNL);
hasso508e53e2004-05-18 18:57:06 +0000741
742 /* Prefix Options */
hasso049207c2004-08-04 20:02:13 +0000743 vty_out (vty, "Prefix Options: xxx%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000744
745 /* Metrics */
746 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
hasso049207c2004-08-04 20:02:13 +0000747 VNL);
hasso508e53e2004-05-18 18:57:06 +0000748 vty_out (vty, "Metric: %d (%d)%s",
hasso049207c2004-08-04 20:02:13 +0000749 route->path.cost, route->path.cost_e2, VNL);
hasso508e53e2004-05-18 18:57:06 +0000750
751 /* Nexthops */
hasso049207c2004-08-04 20:02:13 +0000752 vty_out (vty, "Nexthop:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000753 for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
754 i < OSPF6_MULTI_PATH_LIMIT; i++)
paul718e3742002-12-13 20:15:29 +0000755 {
hasso508e53e2004-05-18 18:57:06 +0000756 /* nexthop */
757 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
758 sizeof (nexthop));
759 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
760 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
hasso049207c2004-08-04 20:02:13 +0000761 vty_out (vty, " %s %s%s", nexthop, ifname, VNL);
paul718e3742002-12-13 20:15:29 +0000762 }
hasso049207c2004-08-04 20:02:13 +0000763 vty_out (vty, "%s", VNL);
paul718e3742002-12-13 20:15:29 +0000764}
765
766void
hasso508e53e2004-05-18 18:57:06 +0000767ospf6_route_show_table_summary (struct vty *vty,
768 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000769{
hasso508e53e2004-05-18 18:57:06 +0000770 struct ospf6_route *route, *prev = NULL;
771 int i, pathtype[OSPF6_PATH_TYPE_MAX];
paul0c083ee2004-10-10 12:54:58 +0000772 unsigned int number = 0;
hasso508e53e2004-05-18 18:57:06 +0000773 int nhinval = 0, ecmp = 0;
hasso4846ef62004-09-03 06:04:00 +0000774 int alternative = 0, destination = 0;
paul718e3742002-12-13 20:15:29 +0000775
hasso508e53e2004-05-18 18:57:06 +0000776 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
777 pathtype[i] = 0;
paul718e3742002-12-13 20:15:29 +0000778
hasso508e53e2004-05-18 18:57:06 +0000779 for (route = ospf6_route_head (table); route;
780 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000781 {
hasso508e53e2004-05-18 18:57:06 +0000782 if (prev == NULL || ! ospf6_route_is_same (prev, route))
783 destination++;
784 else
hasso4846ef62004-09-03 06:04:00 +0000785 alternative++;
hasso508e53e2004-05-18 18:57:06 +0000786 if (! ospf6_nexthop_is_set (&route->nexthop[0]))
787 nhinval++;
788 else if (ospf6_nexthop_is_set (&route->nexthop[1]))
789 ecmp++;
hasso4846ef62004-09-03 06:04:00 +0000790 pathtype[route->path.type]++;
hasso508e53e2004-05-18 18:57:06 +0000791 number++;
hasso4846ef62004-09-03 06:04:00 +0000792
hasso508e53e2004-05-18 18:57:06 +0000793 prev = route;
paul718e3742002-12-13 20:15:29 +0000794 }
hasso508e53e2004-05-18 18:57:06 +0000795
796 assert (number == table->count);
hasso508e53e2004-05-18 18:57:06 +0000797
hasso4846ef62004-09-03 06:04:00 +0000798 vty_out (vty, "Number of OSPFv3 routes: %d%s", number, VNL);
799 vty_out (vty, "Number of Destination: %d%s", destination, VNL);
800 vty_out (vty, "Number of Alternative routes: %d%s", alternative, VNL);
801 vty_out (vty, "Number of Equal Cost Multi Path: %d%s", ecmp, VNL);
802 for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++)
hasso508e53e2004-05-18 18:57:06 +0000803 {
hasso4846ef62004-09-03 06:04:00 +0000804 vty_out (vty, "Number of %s routes: %d%s",
805 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
806 }
807}
808
809void
810ospf6_route_show_table_prefix (struct vty *vty,
811 struct prefix *prefix,
812 struct ospf6_route_table *table)
813{
814 struct ospf6_route *route;
815
816 route = ospf6_route_lookup (prefix, table);
817 if (route == NULL)
818 return;
819
820 ospf6_route_lock (route);
821 while (route && ospf6_route_is_prefix (prefix, route))
822 {
823 /* Specifying a prefix will always display details */
824 ospf6_route_show_detail (vty, route);
825 route = ospf6_route_next (route);
826 }
827 if (route)
828 ospf6_route_unlock (route);
829}
830
831void
832ospf6_route_show_table_address (struct vty *vty,
833 struct prefix *prefix,
834 struct ospf6_route_table *table)
835{
836 struct ospf6_route *route;
837
838 route = ospf6_route_lookup_bestmatch (prefix, table);
839 if (route == NULL)
840 return;
841
842 prefix = &route->prefix;
843 ospf6_route_lock (route);
844 while (route && ospf6_route_is_prefix (prefix, route))
845 {
846 /* Specifying a prefix will always display details */
847 ospf6_route_show_detail (vty, route);
848 route = ospf6_route_next (route);
849 }
850 if (route)
851 ospf6_route_unlock (route);
852}
853
854void
855ospf6_route_show_table_match (struct vty *vty, int detail,
856 struct prefix *prefix,
857 struct ospf6_route_table *table)
858{
859 struct ospf6_route *route;
860 assert (prefix->family);
861
862 route = ospf6_route_match_head (prefix, table);
863 while (route)
864 {
865 if (detail)
866 ospf6_route_show_detail (vty, route);
867 else
868 ospf6_route_show (vty, route);
869 route = ospf6_route_match_next (prefix, route);
870 }
871}
872
873void
874ospf6_route_show_table_type (struct vty *vty, int detail, u_char type,
875 struct ospf6_route_table *table)
876{
877 struct ospf6_route *route;
878
879 route = ospf6_route_head (table);
880 while (route)
881 {
882 if (route->path.type == type)
883 {
884 if (detail)
885 ospf6_route_show_detail (vty, route);
886 else
887 ospf6_route_show (vty, route);
888 }
889 route = ospf6_route_next (route);
890 }
891}
892
893void
894ospf6_route_show_table (struct vty *vty, int detail,
895 struct ospf6_route_table *table)
896{
897 struct ospf6_route *route;
898
899 route = ospf6_route_head (table);
900 while (route)
901 {
902 if (detail)
903 ospf6_route_show_detail (vty, route);
904 else
905 ospf6_route_show (vty, route);
906 route = ospf6_route_next (route);
hasso508e53e2004-05-18 18:57:06 +0000907 }
paul718e3742002-12-13 20:15:29 +0000908}
909
910int
paul0c083ee2004-10-10 12:54:58 +0000911ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
paul718e3742002-12-13 20:15:29 +0000912 struct ospf6_route_table *table)
913{
hasso4846ef62004-09-03 06:04:00 +0000914 int summary = 0;
915 int match = 0;
916 int detail = 0;
917 int slash = 0;
918 int isprefix = 0;
paul718e3742002-12-13 20:15:29 +0000919 int i, ret;
hasso4846ef62004-09-03 06:04:00 +0000920 struct prefix prefix;
921 u_char type = 0;
paul718e3742002-12-13 20:15:29 +0000922
923 memset (&prefix, 0, sizeof (struct prefix));
924
925 for (i = 0; i < argc; i++)
926 {
hasso508e53e2004-05-18 18:57:06 +0000927 if (! strcmp (argv[i], "summary"))
928 {
hasso4846ef62004-09-03 06:04:00 +0000929 summary++;
hasso508e53e2004-05-18 18:57:06 +0000930 continue;
931 }
932
hasso4846ef62004-09-03 06:04:00 +0000933 if (! strcmp (argv[i], "intra-area"))
934 {
935 type = OSPF6_PATH_TYPE_INTRA;
936 continue;
937 }
938
939 if (! strcmp (argv[i], "inter-area"))
940 {
941 type = OSPF6_PATH_TYPE_INTER;
942 continue;
943 }
944
945 if (! strcmp (argv[i], "external-1"))
946 {
947 type = OSPF6_PATH_TYPE_EXTERNAL1;
948 continue;
949 }
950
951 if (! strcmp (argv[i], "external-2"))
952 {
953 type = OSPF6_PATH_TYPE_EXTERNAL2;
954 continue;
955 }
956
paul718e3742002-12-13 20:15:29 +0000957 if (! strcmp (argv[i], "detail"))
958 {
hasso4846ef62004-09-03 06:04:00 +0000959 detail++;
hasso508e53e2004-05-18 18:57:06 +0000960 continue;
paul718e3742002-12-13 20:15:29 +0000961 }
962
hasso508e53e2004-05-18 18:57:06 +0000963 if (! strcmp (argv[i], "match"))
paul718e3742002-12-13 20:15:29 +0000964 {
hasso4846ef62004-09-03 06:04:00 +0000965 match++;
hasso508e53e2004-05-18 18:57:06 +0000966 continue;
paul718e3742002-12-13 20:15:29 +0000967 }
968
hasso508e53e2004-05-18 18:57:06 +0000969 ret = str2prefix (argv[i], &prefix);
hasso4846ef62004-09-03 06:04:00 +0000970 if (ret == 1 && prefix.family == AF_INET6)
hasso508e53e2004-05-18 18:57:06 +0000971 {
hasso4846ef62004-09-03 06:04:00 +0000972 isprefix++;
973 if (strchr (argv[i], '/'))
974 slash++;
975 continue;
hasso508e53e2004-05-18 18:57:06 +0000976 }
977
hasso4846ef62004-09-03 06:04:00 +0000978 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
979 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000980 }
981
hasso508e53e2004-05-18 18:57:06 +0000982 /* Give summary of this route table */
hasso4846ef62004-09-03 06:04:00 +0000983 if (summary)
paul718e3742002-12-13 20:15:29 +0000984 {
hasso508e53e2004-05-18 18:57:06 +0000985 ospf6_route_show_table_summary (vty, table);
paul718e3742002-12-13 20:15:29 +0000986 return CMD_SUCCESS;
987 }
988
hasso508e53e2004-05-18 18:57:06 +0000989 /* Give exact prefix-match route */
hasso4846ef62004-09-03 06:04:00 +0000990 if (isprefix && ! match)
paul718e3742002-12-13 20:15:29 +0000991 {
hasso508e53e2004-05-18 18:57:06 +0000992 /* If exact address, give best matching route */
hasso4846ef62004-09-03 06:04:00 +0000993 if (! slash)
994 ospf6_route_show_table_address (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +0000995 else
hasso4846ef62004-09-03 06:04:00 +0000996 ospf6_route_show_table_prefix (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +0000997
998 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000999 }
1000
hasso4846ef62004-09-03 06:04:00 +00001001 if (match)
1002 ospf6_route_show_table_match (vty, detail, &prefix, table);
1003 else if (type)
1004 ospf6_route_show_table_type (vty, detail, type, table);
hasso508e53e2004-05-18 18:57:06 +00001005 else
hasso4846ef62004-09-03 06:04:00 +00001006 ospf6_route_show_table (vty, detail, table);
paul718e3742002-12-13 20:15:29 +00001007
paul718e3742002-12-13 20:15:29 +00001008 return CMD_SUCCESS;
1009}
1010
hasso4846ef62004-09-03 06:04:00 +00001011void
1012ospf6_linkstate_show_header (struct vty *vty)
hasso508e53e2004-05-18 18:57:06 +00001013{
hasso4846ef62004-09-03 06:04:00 +00001014 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
1015 "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
1016}
1017
1018void
1019ospf6_linkstate_show (struct vty *vty, struct ospf6_route *route)
1020{
1021 u_int32_t router, id;
1022 char routername[16], idname[16], rbits[16], options[16];
1023
1024 router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1025 inet_ntop (AF_INET, &router, routername, sizeof (routername));
1026 id = ospf6_linkstate_prefix_id (&route->prefix);
1027 inet_ntop (AF_INET, &id, idname, sizeof (idname));
1028
1029 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1030 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1031
1032 if (ntohl (id))
1033 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1034 "Network", routername, idname, rbits, options,
1035 (unsigned long) route->path.cost, VNL);
1036 else
1037 vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %lu%s",
1038 "Router", routername, idname, rbits, options,
1039 (unsigned long) route->path.cost, VNL);
1040}
1041
1042
1043void
1044ospf6_linkstate_show_table_exact (struct vty *vty,
1045 struct prefix *prefix,
1046 struct ospf6_route_table *table)
1047{
hasso508e53e2004-05-18 18:57:06 +00001048 struct ospf6_route *route;
1049
hasso4846ef62004-09-03 06:04:00 +00001050 route = ospf6_route_lookup (prefix, table);
1051 if (route == NULL)
1052 return;
1053
1054 ospf6_route_lock (route);
1055 while (route && ospf6_route_is_prefix (prefix, route))
1056 {
1057 /* Specifying a prefix will always display details */
1058 ospf6_route_show_detail (vty, route);
1059 route = ospf6_route_next (route);
1060 }
1061 if (route)
1062 ospf6_route_unlock (route);
1063}
1064
1065void
1066ospf6_linkstate_show_table (struct vty *vty, int detail,
1067 struct ospf6_route_table *table)
1068{
1069 struct ospf6_route *route;
1070
1071 if (! detail)
1072 ospf6_linkstate_show_header (vty);
1073
1074 route = ospf6_route_head (table);
1075 while (route)
1076 {
1077 if (detail)
1078 ospf6_route_show_detail (vty, route);
1079 else
1080 ospf6_linkstate_show (vty, route);
1081 route = ospf6_route_next (route);
1082 }
1083}
1084
1085int
paul0c083ee2004-10-10 12:54:58 +00001086ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
hasso4846ef62004-09-03 06:04:00 +00001087 struct ospf6_route_table *table)
1088{
1089 int detail = 0;
1090 int is_id = 0;
1091 int is_router = 0;
1092 int i, ret;
1093 struct prefix router, id, prefix;
1094
1095 memset (&router, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001096 memset (&id, 0, sizeof (struct prefix));
hasso4846ef62004-09-03 06:04:00 +00001097 memset (&prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001098
1099 for (i = 0; i < argc; i++)
1100 {
hasso508e53e2004-05-18 18:57:06 +00001101 if (! strcmp (argv[i], "detail"))
1102 {
hasso4846ef62004-09-03 06:04:00 +00001103 detail++;
hasso508e53e2004-05-18 18:57:06 +00001104 continue;
1105 }
1106
hasso4846ef62004-09-03 06:04:00 +00001107 if (! is_router)
hasso508e53e2004-05-18 18:57:06 +00001108 {
hasso4846ef62004-09-03 06:04:00 +00001109 ret = str2prefix (argv[i], &router);
1110 if (ret == 1 && router.family == AF_INET)
1111 {
1112 is_router++;
1113 continue;
1114 }
1115 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001116 return CMD_SUCCESS;
1117 }
1118
hasso4846ef62004-09-03 06:04:00 +00001119 if (! is_id)
hasso508e53e2004-05-18 18:57:06 +00001120 {
hasso508e53e2004-05-18 18:57:06 +00001121 ret = str2prefix (argv[i], &id);
hasso4846ef62004-09-03 06:04:00 +00001122 if (ret == 1 && id.family == AF_INET)
hasso508e53e2004-05-18 18:57:06 +00001123 {
hasso4846ef62004-09-03 06:04:00 +00001124 is_id++;
1125 continue;
hasso508e53e2004-05-18 18:57:06 +00001126 }
hasso4846ef62004-09-03 06:04:00 +00001127 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001128 return CMD_SUCCESS;
1129 }
1130
hasso4846ef62004-09-03 06:04:00 +00001131 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +00001132 return CMD_SUCCESS;
1133 }
1134
hasso4846ef62004-09-03 06:04:00 +00001135 if (is_router)
1136 ospf6_linkstate_prefix (router.u.prefix4.s_addr,
1137 id.u.prefix4.s_addr, &prefix);
1138
1139 if (prefix.family)
1140 ospf6_linkstate_show_table_exact (vty, &prefix, table);
hasso508e53e2004-05-18 18:57:06 +00001141 else
hasso4846ef62004-09-03 06:04:00 +00001142 ospf6_linkstate_show_table (vty, detail, table);
hasso508e53e2004-05-18 18:57:06 +00001143
1144 return CMD_SUCCESS;
1145}
1146
hasso4846ef62004-09-03 06:04:00 +00001147
hasso6452df02004-08-15 05:52:07 +00001148void
1149ospf6_brouter_show_header (struct vty *vty)
1150{
1151 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1152 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1153}
1154
1155void
1156ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1157{
1158 u_int32_t adv_router;
1159 char adv[16], rbits[16], options[16], area[16];
1160
1161 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1162 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1163 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1164 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1165 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1166
1167 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1168 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1169 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1170 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1171 area, VNL);
1172}
1173
hasso508e53e2004-05-18 18:57:06 +00001174DEFUN (debug_ospf6_route,
1175 debug_ospf6_route_cmd,
1176 "debug ospf6 route (table|intra-area|inter-area)",
1177 DEBUG_STR
1178 OSPF6_STR
1179 "Debug route table calculation\n"
1180 "Debug detail\n"
1181 "Debug intra-area route calculation\n"
1182 "Debug inter-area route calculation\n"
1183 )
1184{
1185 unsigned char level = 0;
1186
1187 if (! strncmp (argv[0], "table", 5))
1188 level = OSPF6_DEBUG_ROUTE_TABLE;
1189 else if (! strncmp (argv[0], "intra", 5))
1190 level = OSPF6_DEBUG_ROUTE_INTRA;
1191 else if (! strncmp (argv[0], "inter", 5))
1192 level = OSPF6_DEBUG_ROUTE_INTER;
1193 OSPF6_DEBUG_ROUTE_ON (level);
1194 return CMD_SUCCESS;
1195}
1196
1197DEFUN (no_debug_ospf6_route,
1198 no_debug_ospf6_route_cmd,
1199 "no debug ospf6 route (table|intra-area|inter-area)",
1200 NO_STR
1201 DEBUG_STR
1202 OSPF6_STR
1203 "Debug route table calculation\n"
1204 "Debug intra-area route calculation\n")
1205{
1206 unsigned char level = 0;
1207
1208 if (! strncmp (argv[0], "table", 5))
1209 level = OSPF6_DEBUG_ROUTE_TABLE;
1210 else if (! strncmp (argv[0], "intra", 5))
1211 level = OSPF6_DEBUG_ROUTE_INTRA;
1212 else if (! strncmp (argv[0], "inter", 5))
1213 level = OSPF6_DEBUG_ROUTE_INTER;
1214 OSPF6_DEBUG_ROUTE_OFF (level);
1215 return CMD_SUCCESS;
1216}
1217
1218int
1219config_write_ospf6_debug_route (struct vty *vty)
1220{
1221 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
hasso049207c2004-08-04 20:02:13 +00001222 vty_out (vty, "debug ospf6 route table%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001223 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
hasso049207c2004-08-04 20:02:13 +00001224 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001225 if (IS_OSPF6_DEBUG_ROUTE (INTER))
hasso049207c2004-08-04 20:02:13 +00001226 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001227 return 0;
1228}
1229
1230void
1231install_element_ospf6_debug_route ()
1232{
1233 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1234 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1235 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1236 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1237}
1238
1239
1240