blob: 1202a3aeaf76b07bdc718b03ebb8bc9a5ed062a9 [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;
54 char adv_router_str[16];
55 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));
58 snprintf (buf, size, "%s(%lu)", adv_router_str, (u_long) ntohl (id));
paul718e3742002-12-13 20:15:29 +000059}
60
hasso508e53e2004-05-18 18:57:06 +000061/* Global strings for logging */
62char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
63{ "Unknown", "Router", "Network", "Discard", "Linkstate", };
64
65char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
66{ "?", "R", "N", "D", "L", };
67
68char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
69{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
70
71char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
72{ "??", "Ia", "Ie", "E1", "E2", };
73
74
75struct ospf6_route *
76ospf6_route_create ()
paul718e3742002-12-13 20:15:29 +000077{
hasso508e53e2004-05-18 18:57:06 +000078 struct ospf6_route *route;
79 route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
80 return route;
paul718e3742002-12-13 20:15:29 +000081}
82
hasso508e53e2004-05-18 18:57:06 +000083void
84ospf6_route_delete (struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +000085{
hasso508e53e2004-05-18 18:57:06 +000086 XFREE (MTYPE_OSPF6_ROUTE, route);
paul718e3742002-12-13 20:15:29 +000087}
88
hasso508e53e2004-05-18 18:57:06 +000089struct ospf6_route *
90ospf6_route_copy (struct ospf6_route *route)
91{
92 struct ospf6_route *new;
93
94 new = ospf6_route_create ();
95 memcpy (new, route, sizeof (struct ospf6_route));
96 new->rnode = NULL;
97 new->prev = NULL;
98 new->next = NULL;
99 new->lock = 0;
100 return new;
101}
102
103void
104ospf6_route_lock (struct ospf6_route *route)
105{
106 route->lock++;
107}
108
109void
110ospf6_route_unlock (struct ospf6_route *route)
111{
112 assert (route->lock > 0);
113 route->lock--;
114 if (route->lock == 0)
115 ospf6_route_delete (route);
116}
117
118/* Route compare function. If ra is more preferred, it returns
119 less than 0. If rb is more preferred returns greater than 0.
120 Otherwise (neither one is preferred), returns 0 */
121static int
122ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
123{
124 assert (ospf6_route_is_same (ra, rb));
125 assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
126 ra->path.type < OSPF6_PATH_TYPE_MAX);
127 assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
128 rb->path.type < OSPF6_PATH_TYPE_MAX);
129
130 if (ra->type != rb->type)
131 return (ra->type - rb->type);
132
133 if (ra->path.area_id != rb->path.area_id)
134 return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
135
136 if (ra->path.type != rb->path.type)
137 return (ra->path.type - rb->path.type);
138
139 if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
140 {
141 if (ra->path.cost_e2 != rb->path.cost_e2)
142 return (ra->path.cost_e2 - rb->path.cost_e2);
143 }
144 else
145 {
146 if (ra->path.cost != rb->path.cost)
147 return (ra->path.cost - rb->path.cost);
148 }
149
150 return 0;
151}
152
153struct ospf6_route *
154ospf6_route_lookup (struct prefix *prefix,
paul718e3742002-12-13 20:15:29 +0000155 struct ospf6_route_table *table)
156{
157 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000158 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000159
160 node = route_node_lookup (table->table, prefix);
hasso508e53e2004-05-18 18:57:06 +0000161 if (node == NULL)
162 return NULL;
paul718e3742002-12-13 20:15:29 +0000163
hasso508e53e2004-05-18 18:57:06 +0000164 route = (struct ospf6_route *) node->info;
165 return route;
paul718e3742002-12-13 20:15:29 +0000166}
167
hasso508e53e2004-05-18 18:57:06 +0000168struct ospf6_route *
169ospf6_route_lookup_identical (struct ospf6_route *route,
170 struct ospf6_route_table *table)
171{
172 struct ospf6_route *target;
173
174 for (target = ospf6_route_lookup (&route->prefix, table);
175 target; target = target->next)
176 {
177 if (ospf6_route_is_identical (target, route))
178 return target;
179 }
180 return NULL;
181}
182
183struct ospf6_route *
184ospf6_route_lookup_bestmatch (struct prefix *prefix,
185 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000186{
187 struct route_node *node;
hasso508e53e2004-05-18 18:57:06 +0000188 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000189
hasso508e53e2004-05-18 18:57:06 +0000190 node = route_node_match (table->table, prefix);
191 if (node == NULL)
192 return NULL;
193 route_unlock_node (node);
paul718e3742002-12-13 20:15:29 +0000194
hasso508e53e2004-05-18 18:57:06 +0000195 route = (struct ospf6_route *) node->info;
196 return route;
paul718e3742002-12-13 20:15:29 +0000197}
198
hasso508e53e2004-05-18 18:57:06 +0000199#ifndef NDEBUG
200static void
201_route_count_assert (struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000202{
hasso508e53e2004-05-18 18:57:06 +0000203 struct ospf6_route *debug;
204 int num = 0;
205 for (debug = ospf6_route_head (table); debug;
206 debug = ospf6_route_next (debug))
207 num++;
208 assert (num == table->count);
paul718e3742002-12-13 20:15:29 +0000209}
hasso508e53e2004-05-18 18:57:06 +0000210#define ospf6_route_count_assert(t) (_route_count_assert (t))
211#else
212#define ospf6_route_count_assert(t) ((void) 0)
213#endif /*NDEBUG*/
paul718e3742002-12-13 20:15:29 +0000214
hasso508e53e2004-05-18 18:57:06 +0000215struct ospf6_route *
216ospf6_route_add (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000217 struct ospf6_route_table *table)
218{
hasso508e53e2004-05-18 18:57:06 +0000219 struct route_node *node, *nextnode, *prevnode;
220 struct ospf6_route *current = NULL;
221 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
222 char buf[64];
223 struct timeval now;
paul718e3742002-12-13 20:15:29 +0000224
hasso508e53e2004-05-18 18:57:06 +0000225 assert (route->rnode == NULL);
226 assert (route->lock == 0);
227 assert (route->next == NULL);
228 assert (route->prev == NULL);
paul718e3742002-12-13 20:15:29 +0000229
hasso508e53e2004-05-18 18:57:06 +0000230 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
231 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
232 else
233 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000234
hasso508e53e2004-05-18 18:57:06 +0000235 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
236 zlog_info ("route add %s", buf);
paul718e3742002-12-13 20:15:29 +0000237
hasso508e53e2004-05-18 18:57:06 +0000238 gettimeofday (&now, NULL);
239
240 node = route_node_get (table->table, &route->prefix);
241 route->rnode = node;
242
243 /* find place to insert */
244 for (current = node->info; current; current = current->next)
paul718e3742002-12-13 20:15:29 +0000245 {
hasso508e53e2004-05-18 18:57:06 +0000246 if (! ospf6_route_is_same (current, route))
247 next = current;
248 else if (current->type != route->type)
249 prev = current;
250 else if (ospf6_route_is_same_origin (current, route))
251 old = current;
252 else if (ospf6_route_cmp (current, route) > 0)
253 next = current;
254 else
255 prev = current;
256
257 if (old || next)
258 break;
paul718e3742002-12-13 20:15:29 +0000259 }
hasso508e53e2004-05-18 18:57:06 +0000260
261 if (old)
262 {
263 /* if route does not actually change, return unchanged */
264 if (ospf6_route_is_identical (old, route))
265 {
266 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
267 zlog_info (" identical route found, ignore");
268
269 ospf6_route_delete (route);
270 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
271 ospf6_route_count_assert (table);
272 return old;
273 }
274
275 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
276 zlog_info (" old route found, replace");
277
278 /* replace old one if exists */
279 if (node->info == old)
280 {
281 node->info = route;
282 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
283 }
284
285 if (old->prev)
286 old->prev->next = route;
287 route->prev = old->prev;
288 if (old->next)
289 old->next->prev = route;
290 route->next = old->next;
291
292 route->installed = old->installed;
293 route->changed = now;
294
295 ospf6_route_unlock (old); /* will be deleted later */
296 ospf6_route_lock (route);
297
298 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
299 if (table->hook_add)
300 (*table->hook_add) (route);
301
302 ospf6_route_count_assert (table);
303 return route;
304 }
305
306 /* insert if previous or next node found */
307 if (prev || next)
308 {
309 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
310 zlog_info (" another path found, insert");
311
312 if (prev == NULL)
313 prev = next->prev;
314 if (next == NULL)
315 next = prev->next;
316
317 if (prev)
318 prev->next = route;
319 route->prev = prev;
320 if (next)
321 next->prev = route;
322 route->next = next;
323
324 if (node->info == next)
325 {
326 assert (next->rnode == node);
327 node->info = route;
328 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
329 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
330 }
331
332 route->installed = now;
333 route->changed = now;
334
335 ospf6_route_lock (route);
336 table->count++;
337
338 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
339 if (table->hook_add)
340 (*table->hook_add) (route);
341
342 ospf6_route_count_assert (table);
343 return route;
344 }
345
346 /* Else, this is the brand new route regarding to the prefix */
347 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
348 zlog_info (" brand new route, add");
349
350 assert (node->info == NULL);
351 node->info = route;
352 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
353 ospf6_route_lock (route);
354 route->installed = now;
355 route->changed = now;
356
357 /* lookup real existing next route */
358 nextnode = node;
359 route_lock_node (nextnode);
360 do {
361 nextnode = route_next (nextnode);
362 } while (nextnode && nextnode->info == NULL);
363
364 /* set next link */
365 if (nextnode == NULL)
366 route->next = NULL;
paul718e3742002-12-13 20:15:29 +0000367 else
368 {
hasso508e53e2004-05-18 18:57:06 +0000369 route_unlock_node (nextnode);
370
371 next = nextnode->info;
372 route->next = next;
373 next->prev = route;
paul718e3742002-12-13 20:15:29 +0000374 }
375
hasso508e53e2004-05-18 18:57:06 +0000376 /* lookup real existing prev route */
377 prevnode = node;
378 route_lock_node (prevnode);
379 do {
380 prevnode = route_prev (prevnode);
381 } while (prevnode && prevnode->info == NULL);
paul718e3742002-12-13 20:15:29 +0000382
hasso508e53e2004-05-18 18:57:06 +0000383 /* set prev link */
384 if (prevnode == NULL)
385 route->prev = NULL;
paul718e3742002-12-13 20:15:29 +0000386 else
387 {
hasso508e53e2004-05-18 18:57:06 +0000388 route_unlock_node (prevnode);
389
390 prev = prevnode->info;
391 while (prev->next && ospf6_route_is_same (prev, prev->next))
392 prev = prev->next;
393 route->prev = prev;
394 prev->next = route;
paul718e3742002-12-13 20:15:29 +0000395 }
396
hasso508e53e2004-05-18 18:57:06 +0000397 table->count++;
paul718e3742002-12-13 20:15:29 +0000398
hasso508e53e2004-05-18 18:57:06 +0000399 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
400 if (table->hook_add)
401 (*table->hook_add) (route);
paul718e3742002-12-13 20:15:29 +0000402
hasso508e53e2004-05-18 18:57:06 +0000403 ospf6_route_count_assert (table);
404 return route;
paul718e3742002-12-13 20:15:29 +0000405}
406
407void
hasso508e53e2004-05-18 18:57:06 +0000408ospf6_route_remove (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000409 struct ospf6_route_table *table)
410{
hasso508e53e2004-05-18 18:57:06 +0000411 struct route_node *node;
412 struct ospf6_route *current;
413 char buf[64];
paul718e3742002-12-13 20:15:29 +0000414
hasso508e53e2004-05-18 18:57:06 +0000415 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
416 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
417 else
418 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000419
hasso508e53e2004-05-18 18:57:06 +0000420 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
421 zlog_info ("route remove: %s", buf);
422
423 node = route_node_lookup (table->table, &route->prefix);
424 assert (node);
425
426 /* find the route to remove, making sure that the route pointer
427 is from the route table. */
428 current = node->info;
429 while (current && ospf6_route_is_same (current, route))
paul718e3742002-12-13 20:15:29 +0000430 {
hasso508e53e2004-05-18 18:57:06 +0000431 if (current == route)
432 break;
433 current = current->next;
434 }
435 assert (current == route);
436
437 /* adjust doubly linked list */
438 if (route->prev)
439 route->prev->next = route->next;
440 if (route->next)
441 route->next->prev = route->prev;
442
443 if (node->info == route)
444 {
445 if (route->next && ospf6_route_is_same (route->next, route))
paul718e3742002-12-13 20:15:29 +0000446 {
hasso508e53e2004-05-18 18:57:06 +0000447 node->info = route->next;
448 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
paul718e3742002-12-13 20:15:29 +0000449 }
hasso508e53e2004-05-18 18:57:06 +0000450 else
451 node->info = NULL; /* should unlock route_node here ? */
paul718e3742002-12-13 20:15:29 +0000452 }
453
paul718e3742002-12-13 20:15:29 +0000454 if (table->hook_remove)
hasso508e53e2004-05-18 18:57:06 +0000455 (*table->hook_remove) (route);
paul718e3742002-12-13 20:15:29 +0000456
hasso508e53e2004-05-18 18:57:06 +0000457 ospf6_route_unlock (route);
458 table->count--;
paul718e3742002-12-13 20:15:29 +0000459
hasso508e53e2004-05-18 18:57:06 +0000460 ospf6_route_count_assert (table);
461}
paul718e3742002-12-13 20:15:29 +0000462
hasso508e53e2004-05-18 18:57:06 +0000463struct ospf6_route *
464ospf6_route_head (struct ospf6_route_table *table)
465{
466 struct route_node *node;
467 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000468
hasso508e53e2004-05-18 18:57:06 +0000469 node = route_top (table->table);
470 if (node == NULL)
471 return NULL;
472
473 /* skip to the real existing entry */
474 while (node && node->info == NULL)
475 node = route_next (node);
476 if (node == NULL)
477 return NULL;
478
479 route_unlock_node (node);
480 assert (node->info);
481
482 route = (struct ospf6_route *) node->info;
483 assert (route->prev == NULL);
484 ospf6_route_lock (route);
485 return route;
486}
487
488struct ospf6_route *
489ospf6_route_next (struct ospf6_route *route)
490{
491 struct ospf6_route *next = route->next;
492
493 ospf6_route_unlock (route);
494 if (next)
495 ospf6_route_lock (next);
496
497 return next;
498}
499
500struct ospf6_route *
501ospf6_route_best_next (struct ospf6_route *route)
502{
503 struct route_node *rnode;
504 struct ospf6_route *next;
505
506 rnode = route->rnode;
507 route_lock_node (rnode);
508 rnode = route_next (rnode);
509 while (rnode && rnode->info == NULL)
510 rnode = route_next (rnode);
511 if (rnode == NULL)
512 return NULL;
513 route_unlock_node (rnode);
514
515 assert (rnode->info);
516 next = (struct ospf6_route *) rnode->info;
517 ospf6_route_unlock (route);
518 ospf6_route_lock (next);
519 return next;
520}
521
522/* Macro version of check_bit (). */
523#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
524
525struct ospf6_route *
526ospf6_route_match_head (struct prefix *prefix,
527 struct ospf6_route_table *table)
528{
529 struct route_node *node;
530 struct ospf6_route *route;
531
532 /* Walk down tree. */
533 node = table->table->top;
534 while (node && node->p.prefixlen < prefix->prefixlen &&
535 prefix_match (&node->p, prefix))
536 node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
537
538 if (node)
539 route_lock_node (node);
540 while (node && node->info == NULL)
541 node = route_next (node);
542 if (node == NULL)
543 return NULL;
544 route_unlock_node (node);
545
546 if (! prefix_match (prefix, &node->p))
547 return NULL;
548
549 route = node->info;
550 ospf6_route_lock (route);
551 return route;
552}
553
554struct ospf6_route *
555ospf6_route_match_next (struct prefix *prefix,
556 struct ospf6_route *route)
557{
558 struct ospf6_route *next;
559
560 next = ospf6_route_next (route);
561 if (next && ! prefix_match (prefix, &next->prefix))
562 {
563 ospf6_route_unlock (next);
564 next = NULL;
565 }
566
567 return next;
paul718e3742002-12-13 20:15:29 +0000568}
569
570void
571ospf6_route_remove_all (struct ospf6_route_table *table)
572{
hasso508e53e2004-05-18 18:57:06 +0000573 struct ospf6_route *route;
574 for (route = ospf6_route_head (table); route;
575 route = ospf6_route_next (route))
576 ospf6_route_remove (route, table);
paul718e3742002-12-13 20:15:29 +0000577}
578
paul718e3742002-12-13 20:15:29 +0000579struct ospf6_route_table *
hasso508e53e2004-05-18 18:57:06 +0000580ospf6_route_table_create ()
paul718e3742002-12-13 20:15:29 +0000581{
paul718e3742002-12-13 20:15:29 +0000582 struct ospf6_route_table *new;
paul718e3742002-12-13 20:15:29 +0000583 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
paul718e3742002-12-13 20:15:29 +0000584 new->table = route_table_init ();
paul718e3742002-12-13 20:15:29 +0000585 return new;
586}
587
588void
589ospf6_route_table_delete (struct ospf6_route_table *table)
590{
paul718e3742002-12-13 20:15:29 +0000591 ospf6_route_remove_all (table);
592 route_table_finish (table->table);
paul718e3742002-12-13 20:15:29 +0000593 XFREE (MTYPE_OSPF6_ROUTE, table);
594}
595
paul718e3742002-12-13 20:15:29 +0000596
597
598/* VTY commands */
hasso508e53e2004-05-18 18:57:06 +0000599void
600ospf6_route_show (struct vty *vty, struct ospf6_route *route)
601{
602 int i;
603 char destination[64], nexthop[64];
604 char duration[16], ifname[IFNAMSIZ];
605 struct timeval now, res;
606
607 gettimeofday (&now, (struct timezone *) NULL);
608 timersub (&now, &route->changed, &res);
609 timerstring (&res, duration, sizeof (duration));
610
611 /* destination */
612 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
613 ospf6_linkstate_prefix2str (&route->prefix, destination,
614 sizeof (destination));
615 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
616 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
617 destination, sizeof (destination));
618 else
619 prefix2str (&route->prefix, destination, sizeof (destination));
620
621 /* nexthop */
622 inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
623 sizeof (nexthop));
624 if (! if_indextoname (route->nexthop[0].ifindex, ifname))
625 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
626
627 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
628 (ospf6_route_is_best (route) ? '*' : ' '),
629 OSPF6_DEST_TYPE_SUBSTR (route->type),
630 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
hasso049207c2004-08-04 20:02:13 +0000631 destination, nexthop, ifname, duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000632
633 for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
634 i < OSPF6_MULTI_PATH_LIMIT; i++)
635 {
636 /* nexthop */
637 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
638 sizeof (nexthop));
639 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
640 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
641
642 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
hasso049207c2004-08-04 20:02:13 +0000643 ' ', "", "", "", nexthop, ifname, "", VNL);
hasso508e53e2004-05-18 18:57:06 +0000644 }
645}
paul718e3742002-12-13 20:15:29 +0000646
647void
hasso508e53e2004-05-18 18:57:06 +0000648ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +0000649{
hasso508e53e2004-05-18 18:57:06 +0000650 char destination[64], nexthop[64], ifname[IFNAMSIZ];
651 char area_id[16], id[16], adv_router[16], capa[16], options[16];
paul718e3742002-12-13 20:15:29 +0000652 struct timeval now, res;
653 char duration[16];
hasso508e53e2004-05-18 18:57:06 +0000654 int i;
paul718e3742002-12-13 20:15:29 +0000655
656 gettimeofday (&now, (struct timezone *) NULL);
657
658 /* destination */
hasso508e53e2004-05-18 18:57:06 +0000659 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
660 ospf6_linkstate_prefix2str (&route->prefix, destination,
661 sizeof (destination));
662 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
663 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
664 destination, sizeof (destination));
paul718e3742002-12-13 20:15:29 +0000665 else
hasso508e53e2004-05-18 18:57:06 +0000666 prefix2str (&route->prefix, destination, sizeof (destination));
hasso049207c2004-08-04 20:02:13 +0000667 vty_out (vty, "Destination: %s%s", destination, VNL);
paul718e3742002-12-13 20:15:29 +0000668
hasso508e53e2004-05-18 18:57:06 +0000669 /* destination type */
670 vty_out (vty, "Destination type: %s%s",
671 OSPF6_DEST_TYPE_NAME (route->type),
hasso049207c2004-08-04 20:02:13 +0000672 VNL);
hasso508e53e2004-05-18 18:57:06 +0000673
674 /* Time */
675 timersub (&now, &route->installed, &res);
676 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000677 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000678
679 timersub (&now, &route->changed, &res);
680 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000681 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000682
683 /* Debugging info */
684 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
685 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
686 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
687 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
688 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
hasso049207c2004-08-04 20:02:13 +0000689 VNL);
hasso508e53e2004-05-18 18:57:06 +0000690 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000691 route->prev, route, route->next, VNL);
hasso508e53e2004-05-18 18:57:06 +0000692
693 /* Path section */
694
695 /* Area-ID */
696 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
hasso049207c2004-08-04 20:02:13 +0000697 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
hasso508e53e2004-05-18 18:57:06 +0000698
699 /* Path type */
700 vty_out (vty, "Path Type: %s%s",
hasso049207c2004-08-04 20:02:13 +0000701 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
hasso508e53e2004-05-18 18:57:06 +0000702
703 /* LS Origin */
704 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
705 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
706 sizeof (adv_router));
707 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
708 OSPF6_LSTYPE_NAME (route->path.origin.type),
hasso049207c2004-08-04 20:02:13 +0000709 id, adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000710
711 /* Options */
712 ospf6_options_printbuf (route->path.options, options, sizeof (options));
hasso049207c2004-08-04 20:02:13 +0000713 vty_out (vty, "Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000714
715 /* Router Bits */
716 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
hasso049207c2004-08-04 20:02:13 +0000717 vty_out (vty, "Router Bits: %s%s", capa, VNL);
hasso508e53e2004-05-18 18:57:06 +0000718
719 /* Prefix Options */
hasso049207c2004-08-04 20:02:13 +0000720 vty_out (vty, "Prefix Options: xxx%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000721
722 /* Metrics */
723 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
hasso049207c2004-08-04 20:02:13 +0000724 VNL);
hasso508e53e2004-05-18 18:57:06 +0000725 vty_out (vty, "Metric: %d (%d)%s",
hasso049207c2004-08-04 20:02:13 +0000726 route->path.cost, route->path.cost_e2, VNL);
hasso508e53e2004-05-18 18:57:06 +0000727
728 /* Nexthops */
hasso049207c2004-08-04 20:02:13 +0000729 vty_out (vty, "Nexthop:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000730 for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
731 i < OSPF6_MULTI_PATH_LIMIT; i++)
paul718e3742002-12-13 20:15:29 +0000732 {
hasso508e53e2004-05-18 18:57:06 +0000733 /* nexthop */
734 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
735 sizeof (nexthop));
736 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
737 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
hasso049207c2004-08-04 20:02:13 +0000738 vty_out (vty, " %s %s%s", nexthop, ifname, VNL);
paul718e3742002-12-13 20:15:29 +0000739 }
hasso049207c2004-08-04 20:02:13 +0000740 vty_out (vty, "%s", VNL);
paul718e3742002-12-13 20:15:29 +0000741}
742
743void
hasso508e53e2004-05-18 18:57:06 +0000744ospf6_route_show_table_summary (struct vty *vty,
745 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000746{
hasso508e53e2004-05-18 18:57:06 +0000747 struct ospf6_route *route, *prev = NULL;
748 int i, pathtype[OSPF6_PATH_TYPE_MAX];
749 int number = 0;
750 int nhinval = 0, ecmp = 0;
751 int multipath = 0, destination = 0;
752 int desttype = 0, desttype_mismatch = 0;
paul718e3742002-12-13 20:15:29 +0000753
hasso508e53e2004-05-18 18:57:06 +0000754 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
755 pathtype[i] = 0;
paul718e3742002-12-13 20:15:29 +0000756
hasso508e53e2004-05-18 18:57:06 +0000757 for (route = ospf6_route_head (table); route;
758 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000759 {
hasso508e53e2004-05-18 18:57:06 +0000760 if (desttype == 0)
761 desttype = route->type;
762 else if (desttype != route->type)
763 desttype_mismatch++;
paul718e3742002-12-13 20:15:29 +0000764
hasso508e53e2004-05-18 18:57:06 +0000765 if (prev == NULL || ! ospf6_route_is_same (prev, route))
766 destination++;
767 else
768 multipath++;
paul718e3742002-12-13 20:15:29 +0000769
hasso508e53e2004-05-18 18:57:06 +0000770 if (! ospf6_nexthop_is_set (&route->nexthop[0]))
771 nhinval++;
772 else if (ospf6_nexthop_is_set (&route->nexthop[1]))
773 ecmp++;
paul718e3742002-12-13 20:15:29 +0000774
hasso508e53e2004-05-18 18:57:06 +0000775 if (prev == NULL || ! ospf6_route_is_same (prev, route))
776 pathtype[route->path.type]++;
paul718e3742002-12-13 20:15:29 +0000777
hasso508e53e2004-05-18 18:57:06 +0000778 number++;
779 prev = route;
paul718e3742002-12-13 20:15:29 +0000780 }
hasso508e53e2004-05-18 18:57:06 +0000781
782 assert (number == table->count);
783 vty_out (vty, "Number of Destination: %d (%d routes)%s",
hasso049207c2004-08-04 20:02:13 +0000784 destination, number, VNL);
hasso508e53e2004-05-18 18:57:06 +0000785 if (multipath)
hasso049207c2004-08-04 20:02:13 +0000786 vty_out (vty, " Number of Multi-path: %d%s", multipath, VNL);
hasso508e53e2004-05-18 18:57:06 +0000787 if (desttype_mismatch)
788 vty_out (vty, " Number of Different Dest-type: %d%s",
hasso049207c2004-08-04 20:02:13 +0000789 desttype_mismatch, VNL);
hasso508e53e2004-05-18 18:57:06 +0000790 if (ecmp)
791 vty_out (vty, " Number of Equal Cost Multi Path: %d%s",
hasso049207c2004-08-04 20:02:13 +0000792 ecmp, VNL);
hasso508e53e2004-05-18 18:57:06 +0000793 if (ecmp)
794 vty_out (vty, " Number of Invalid Nexthop: %d%s",
hasso049207c2004-08-04 20:02:13 +0000795 nhinval, VNL);
hasso508e53e2004-05-18 18:57:06 +0000796
797 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
798 {
799 if (pathtype[i])
800 vty_out (vty, " Number of %s routes: %d%s",
hasso049207c2004-08-04 20:02:13 +0000801 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000802 }
paul718e3742002-12-13 20:15:29 +0000803}
804
805int
806ospf6_route_table_show (struct vty *vty, int argc, char **argv,
807 struct ospf6_route_table *table)
808{
hasso508e53e2004-05-18 18:57:06 +0000809 unsigned char flag = 0;
810#define MATCH 0x01
811#define DETAIL 0x02
812#define PREFIX 0x04
813#define SUMMARY 0x08
paul718e3742002-12-13 20:15:29 +0000814 int i, ret;
hasso508e53e2004-05-18 18:57:06 +0000815 struct prefix prefix, *p;
816 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000817
818 memset (&prefix, 0, sizeof (struct prefix));
819
820 for (i = 0; i < argc; i++)
821 {
hasso508e53e2004-05-18 18:57:06 +0000822 /* set "detail" */
823 if (! strcmp (argv[i], "summary"))
824 {
825 SET_FLAG (flag, SUMMARY);
826 continue;
827 }
828
829 /* set "detail" */
paul718e3742002-12-13 20:15:29 +0000830 if (! strcmp (argv[i], "detail"))
831 {
hasso508e53e2004-05-18 18:57:06 +0000832 SET_FLAG (flag, DETAIL);
833 continue;
paul718e3742002-12-13 20:15:29 +0000834 }
835
hasso508e53e2004-05-18 18:57:06 +0000836 /* set "match" */
837 if (! strcmp (argv[i], "match"))
paul718e3742002-12-13 20:15:29 +0000838 {
hasso508e53e2004-05-18 18:57:06 +0000839 SET_FLAG (flag, MATCH);
840 continue;
paul718e3742002-12-13 20:15:29 +0000841 }
842
hasso508e53e2004-05-18 18:57:06 +0000843 if (prefix.family)
paul718e3742002-12-13 20:15:29 +0000844 {
hasso049207c2004-08-04 20:02:13 +0000845 vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000846 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000847 }
hasso508e53e2004-05-18 18:57:06 +0000848
849 ret = str2prefix (argv[i], &prefix);
850 if (ret != 1 || prefix.family != AF_INET6)
851 {
hasso049207c2004-08-04 20:02:13 +0000852 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000853 return CMD_SUCCESS;
854 }
855
856 if (strchr (argv[i], '/'))
857 SET_FLAG (flag, PREFIX);
paul718e3742002-12-13 20:15:29 +0000858 }
859
hasso508e53e2004-05-18 18:57:06 +0000860 /* Give summary of this route table */
861 if (CHECK_FLAG (flag, SUMMARY))
paul718e3742002-12-13 20:15:29 +0000862 {
hasso508e53e2004-05-18 18:57:06 +0000863 ospf6_route_show_table_summary (vty, table);
paul718e3742002-12-13 20:15:29 +0000864 return CMD_SUCCESS;
865 }
866
hasso508e53e2004-05-18 18:57:06 +0000867 /* Give exact prefix-match route */
868 if (prefix.family && ! CHECK_FLAG (flag, MATCH))
paul718e3742002-12-13 20:15:29 +0000869 {
hasso508e53e2004-05-18 18:57:06 +0000870 /* If exact address, give best matching route */
871 if (! CHECK_FLAG (flag, PREFIX))
872 route = ospf6_route_lookup_bestmatch (&prefix, table);
873 else
874 route = ospf6_route_lookup (&prefix, table);
875
876 if (route)
877 {
878 ospf6_route_lock (route);
879 p = &route->prefix;
880 }
881
882 while (route && ospf6_route_is_prefix (p, route))
883 {
884 /* Seaching an entry will always display details */
885 if (route)
886 ospf6_route_show_detail (vty, route);
887
888 route = ospf6_route_next (route);
889 }
890
891 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000892 }
893
hasso508e53e2004-05-18 18:57:06 +0000894 if (prefix.family == 0)
895 route = ospf6_route_head (table);
896 else
897 route = ospf6_route_match_head (&prefix, table);
898
899 while (route)
paul718e3742002-12-13 20:15:29 +0000900 {
hasso508e53e2004-05-18 18:57:06 +0000901 if (CHECK_FLAG (flag, DETAIL))
paul718e3742002-12-13 20:15:29 +0000902 ospf6_route_show_detail (vty, route);
903 else
904 ospf6_route_show (vty, route);
905
hasso508e53e2004-05-18 18:57:06 +0000906 if (prefix.family == 0)
907 route = ospf6_route_next (route);
908 else
909 route = ospf6_route_match_next (&prefix, route);
paul718e3742002-12-13 20:15:29 +0000910 }
911
paul718e3742002-12-13 20:15:29 +0000912 return CMD_SUCCESS;
913}
914
hasso508e53e2004-05-18 18:57:06 +0000915
916int
917ospf6_lsentry_table_show (struct vty *vty, int argc, char **argv,
918 struct ospf6_route_table *table)
919{
920 unsigned char flag = 0;
921#define MATCH 0x01
922#define DETAIL 0x02
923 int i, ret;
924 struct prefix adv_router, id, prefix;
925 struct ospf6_route *route;
926
927 memset (&adv_router, 0, sizeof (struct prefix));
928 memset (&id, 0, sizeof (struct prefix));
929
930 for (i = 0; i < argc; i++)
931 {
932 /* set "detail" */
933 if (! strcmp (argv[i], "detail"))
934 {
935 SET_FLAG (flag, DETAIL);
936 continue;
937 }
938
939 /* set "match" */
940 if (! strcmp (argv[i], "match"))
941 {
942 SET_FLAG (flag, MATCH);
943 continue;
944 }
945
946 if (adv_router.family && id.family)
947 {
hasso049207c2004-08-04 20:02:13 +0000948 vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000949 return CMD_SUCCESS;
950 }
951
952 if (adv_router.family == 0)
953 {
954 ret = str2prefix (argv[i], &adv_router);
955 if (ret != 1)
956 {
957 if (! strcmp (argv[i], "*"))
958 {
959 adv_router.family = AF_INET;
960 adv_router.prefixlen = 0;
961 ret = 1;
962 }
963 }
964 if (ret != 1)
965 {
hasso049207c2004-08-04 20:02:13 +0000966 vty_out (vty, "Invalid Router-ID: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000967 return CMD_SUCCESS;
968 }
969 }
970 else if (id.family == 0)
971 {
972 unsigned long val;
973 char *endptr;
974
975 ret = str2prefix (argv[i], &id);
976 if (ret != 1)
977 {
978 val = strtoul (argv[i], &endptr, 0);
979 if (val != ULONG_MAX && *endptr == '\0')
980 {
981 id.u.prefix4.s_addr = val;
982 ret = 1;
983 }
984 }
985
986 if (ret != 1)
987 {
988 vty_out (vty, "Invalid Link state ID: %s%s", argv[i],
hasso049207c2004-08-04 20:02:13 +0000989 VNL);
hasso508e53e2004-05-18 18:57:06 +0000990 return CMD_WARNING;
991 }
992 }
993 }
994
995 /* Encode to linkstate prefix */
996 if (adv_router.family)
997 {
998 if (adv_router.prefixlen == 0 &&
999 id.family && id.prefixlen != IPV4_MAX_BITLEN)
1000 {
1001 vty_out (vty, "Specifying Link State ID by prefix is not allowed%s"
1002 "when specifying Router-ID as wildcard%s",
hasso049207c2004-08-04 20:02:13 +00001003 VNL, VNL);
hasso508e53e2004-05-18 18:57:06 +00001004 return CMD_SUCCESS;
1005 }
1006 else if (adv_router.prefixlen != 0 &&
1007 adv_router.prefixlen != IPV4_MAX_BITLEN && id.family)
1008 {
1009 vty_out (vty, "Specifying Link State ID is not allowed%s"
1010 "when specifying Router-ID by prefix%s",
hasso049207c2004-08-04 20:02:13 +00001011 VNL, VNL);
hasso508e53e2004-05-18 18:57:06 +00001012 return CMD_SUCCESS;
1013 }
1014
1015 if (adv_router.prefixlen == 0)
1016 ospf6_linkstate_prefix (0, id.u.prefix4.s_addr, &prefix);
1017 else if (adv_router.prefixlen != IPV4_MAX_BITLEN)
1018 {
1019 ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr, 0, &prefix);
1020 prefix.prefixlen = adv_router.prefixlen;
1021 SET_FLAG (flag, MATCH);
1022 }
1023 else
1024 {
1025 ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr,
1026 id.u.prefix4.s_addr, &prefix);
1027 prefix.prefixlen = adv_router.prefixlen + id.prefixlen;
1028 if (prefix.prefixlen != 64)
1029 SET_FLAG (flag, MATCH);
1030 }
1031 }
1032
1033 /* give exact match entry */
1034 if (adv_router.family && adv_router.prefixlen == IPV4_MAX_BITLEN &&
1035 id.family && id.prefixlen == IPV4_MAX_BITLEN)
1036 {
1037 route = ospf6_route_lookup (&prefix, table);
1038 if (route)
1039 ospf6_route_show_detail (vty, route);
1040 return CMD_SUCCESS;
1041 }
1042
1043 if (CHECK_FLAG (flag, MATCH))
1044 route = ospf6_route_match_head (&prefix, table);
1045 else
1046 route = ospf6_route_head (table);
1047
1048 while (route)
1049 {
1050 if (! adv_router.family ||
1051 (CHECK_FLAG (flag, MATCH) &&
1052 prefix_match (&prefix, &route->prefix)) ||
1053 (adv_router.prefixlen == 0 && id.family &&
1054 ospf6_linkstate_prefix_id (&prefix) ==
1055 ospf6_linkstate_prefix_id (&route->prefix)))
1056 {
1057 if (CHECK_FLAG (flag, DETAIL))
1058 ospf6_route_show_detail (vty, route);
1059 else
1060 ospf6_route_show (vty, route);
1061 }
1062
1063 if (CHECK_FLAG (flag, MATCH))
1064 route = ospf6_route_match_next (&prefix, route);
1065 else
1066 route = ospf6_route_next (route);
1067 }
1068
1069 return CMD_SUCCESS;
1070}
1071
hasso6452df02004-08-15 05:52:07 +00001072void
1073ospf6_brouter_show_header (struct vty *vty)
1074{
1075 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1076 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1077}
1078
1079void
1080ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1081{
1082 u_int32_t adv_router;
1083 char adv[16], rbits[16], options[16], area[16];
1084
1085 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1086 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1087 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1088 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1089 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1090
1091 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1092 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1093 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1094 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1095 area, VNL);
1096}
1097
hasso508e53e2004-05-18 18:57:06 +00001098DEFUN (debug_ospf6_route,
1099 debug_ospf6_route_cmd,
1100 "debug ospf6 route (table|intra-area|inter-area)",
1101 DEBUG_STR
1102 OSPF6_STR
1103 "Debug route table calculation\n"
1104 "Debug detail\n"
1105 "Debug intra-area route calculation\n"
1106 "Debug inter-area route calculation\n"
1107 )
1108{
1109 unsigned char level = 0;
1110
1111 if (! strncmp (argv[0], "table", 5))
1112 level = OSPF6_DEBUG_ROUTE_TABLE;
1113 else if (! strncmp (argv[0], "intra", 5))
1114 level = OSPF6_DEBUG_ROUTE_INTRA;
1115 else if (! strncmp (argv[0], "inter", 5))
1116 level = OSPF6_DEBUG_ROUTE_INTER;
1117 OSPF6_DEBUG_ROUTE_ON (level);
1118 return CMD_SUCCESS;
1119}
1120
1121DEFUN (no_debug_ospf6_route,
1122 no_debug_ospf6_route_cmd,
1123 "no debug ospf6 route (table|intra-area|inter-area)",
1124 NO_STR
1125 DEBUG_STR
1126 OSPF6_STR
1127 "Debug route table calculation\n"
1128 "Debug intra-area route calculation\n")
1129{
1130 unsigned char level = 0;
1131
1132 if (! strncmp (argv[0], "table", 5))
1133 level = OSPF6_DEBUG_ROUTE_TABLE;
1134 else if (! strncmp (argv[0], "intra", 5))
1135 level = OSPF6_DEBUG_ROUTE_INTRA;
1136 else if (! strncmp (argv[0], "inter", 5))
1137 level = OSPF6_DEBUG_ROUTE_INTER;
1138 OSPF6_DEBUG_ROUTE_OFF (level);
1139 return CMD_SUCCESS;
1140}
1141
1142int
1143config_write_ospf6_debug_route (struct vty *vty)
1144{
1145 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
hasso049207c2004-08-04 20:02:13 +00001146 vty_out (vty, "debug ospf6 route table%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001147 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
hasso049207c2004-08-04 20:02:13 +00001148 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001149 if (IS_OSPF6_DEBUG_ROUTE (INTER))
hasso049207c2004-08-04 20:02:13 +00001150 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001151 return 0;
1152}
1153
1154void
1155install_element_ospf6_debug_route ()
1156{
1157 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1158 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1159 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1160 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1161}
1162
1163
1164