blob: dae9222658b17975de8cbdef4f20ee33324ceb62 [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;
hassoccb59b12004-08-25 09:10:37 +0000204 char buf[64];
hasso508e53e2004-05-18 18:57:06 +0000205 int num = 0;
206 for (debug = ospf6_route_head (table); debug;
207 debug = ospf6_route_next (debug))
208 num++;
hassoccb59b12004-08-25 09:10:37 +0000209
210 if (num == table->count)
211 return;
212
213 zlog_info ("PANIC !! table[%p]->count = %d, real = %d",
214 table, table->count, num);
215 for (debug = ospf6_route_head (table); debug;
216 debug = ospf6_route_next (debug))
217 {
218 prefix2str (&debug->prefix, buf, sizeof (buf));
219 zlog_info ("%p %p %s", debug->prev, debug->next, buf);
220 }
221 zlog_info ("DUMP END");
222
hasso508e53e2004-05-18 18:57:06 +0000223 assert (num == table->count);
paul718e3742002-12-13 20:15:29 +0000224}
hasso508e53e2004-05-18 18:57:06 +0000225#define ospf6_route_count_assert(t) (_route_count_assert (t))
226#else
227#define ospf6_route_count_assert(t) ((void) 0)
228#endif /*NDEBUG*/
paul718e3742002-12-13 20:15:29 +0000229
hasso508e53e2004-05-18 18:57:06 +0000230struct ospf6_route *
231ospf6_route_add (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000232 struct ospf6_route_table *table)
233{
hasso508e53e2004-05-18 18:57:06 +0000234 struct route_node *node, *nextnode, *prevnode;
235 struct ospf6_route *current = NULL;
236 struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
237 char buf[64];
238 struct timeval now;
paul718e3742002-12-13 20:15:29 +0000239
hasso508e53e2004-05-18 18:57:06 +0000240 assert (route->rnode == NULL);
241 assert (route->lock == 0);
242 assert (route->next == NULL);
243 assert (route->prev == NULL);
paul718e3742002-12-13 20:15:29 +0000244
hasso508e53e2004-05-18 18:57:06 +0000245 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
246 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
247 else
248 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000249
hasso508e53e2004-05-18 18:57:06 +0000250 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
251 zlog_info ("route add %s", buf);
paul718e3742002-12-13 20:15:29 +0000252
hasso508e53e2004-05-18 18:57:06 +0000253 gettimeofday (&now, NULL);
254
255 node = route_node_get (table->table, &route->prefix);
256 route->rnode = node;
257
258 /* find place to insert */
259 for (current = node->info; current; current = current->next)
paul718e3742002-12-13 20:15:29 +0000260 {
hasso508e53e2004-05-18 18:57:06 +0000261 if (! ospf6_route_is_same (current, route))
262 next = current;
263 else if (current->type != route->type)
264 prev = current;
265 else if (ospf6_route_is_same_origin (current, route))
266 old = current;
267 else if (ospf6_route_cmp (current, route) > 0)
268 next = current;
269 else
270 prev = current;
271
272 if (old || next)
273 break;
paul718e3742002-12-13 20:15:29 +0000274 }
hasso508e53e2004-05-18 18:57:06 +0000275
276 if (old)
277 {
278 /* if route does not actually change, return unchanged */
279 if (ospf6_route_is_identical (old, route))
280 {
281 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
282 zlog_info (" identical route found, ignore");
283
284 ospf6_route_delete (route);
285 SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
286 ospf6_route_count_assert (table);
287 return old;
288 }
289
290 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
291 zlog_info (" old route found, replace");
292
293 /* replace old one if exists */
294 if (node->info == old)
295 {
296 node->info = route;
297 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
298 }
299
300 if (old->prev)
301 old->prev->next = route;
302 route->prev = old->prev;
303 if (old->next)
304 old->next->prev = route;
305 route->next = old->next;
306
307 route->installed = old->installed;
308 route->changed = now;
309
310 ospf6_route_unlock (old); /* will be deleted later */
311 ospf6_route_lock (route);
312
313 SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
314 if (table->hook_add)
315 (*table->hook_add) (route);
316
317 ospf6_route_count_assert (table);
318 return route;
319 }
320
321 /* insert if previous or next node found */
322 if (prev || next)
323 {
324 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
325 zlog_info (" another path found, insert");
326
327 if (prev == NULL)
328 prev = next->prev;
329 if (next == NULL)
330 next = prev->next;
331
332 if (prev)
333 prev->next = route;
334 route->prev = prev;
335 if (next)
336 next->prev = route;
337 route->next = next;
338
339 if (node->info == next)
340 {
341 assert (next->rnode == node);
342 node->info = route;
343 UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
344 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
345 }
346
347 route->installed = now;
348 route->changed = now;
349
350 ospf6_route_lock (route);
351 table->count++;
352
353 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
354 if (table->hook_add)
355 (*table->hook_add) (route);
356
357 ospf6_route_count_assert (table);
358 return route;
359 }
360
361 /* Else, this is the brand new route regarding to the prefix */
362 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
363 zlog_info (" brand new route, add");
364
365 assert (node->info == NULL);
366 node->info = route;
367 SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
368 ospf6_route_lock (route);
369 route->installed = now;
370 route->changed = now;
371
372 /* lookup real existing next route */
373 nextnode = node;
374 route_lock_node (nextnode);
375 do {
376 nextnode = route_next (nextnode);
377 } while (nextnode && nextnode->info == NULL);
378
379 /* set next link */
380 if (nextnode == NULL)
381 route->next = NULL;
paul718e3742002-12-13 20:15:29 +0000382 else
383 {
hasso508e53e2004-05-18 18:57:06 +0000384 route_unlock_node (nextnode);
385
386 next = nextnode->info;
387 route->next = next;
388 next->prev = route;
paul718e3742002-12-13 20:15:29 +0000389 }
390
hasso508e53e2004-05-18 18:57:06 +0000391 /* lookup real existing prev route */
392 prevnode = node;
393 route_lock_node (prevnode);
394 do {
395 prevnode = route_prev (prevnode);
396 } while (prevnode && prevnode->info == NULL);
paul718e3742002-12-13 20:15:29 +0000397
hasso508e53e2004-05-18 18:57:06 +0000398 /* set prev link */
399 if (prevnode == NULL)
400 route->prev = NULL;
paul718e3742002-12-13 20:15:29 +0000401 else
402 {
hasso508e53e2004-05-18 18:57:06 +0000403 route_unlock_node (prevnode);
404
405 prev = prevnode->info;
406 while (prev->next && ospf6_route_is_same (prev, prev->next))
407 prev = prev->next;
408 route->prev = prev;
409 prev->next = route;
paul718e3742002-12-13 20:15:29 +0000410 }
411
hasso508e53e2004-05-18 18:57:06 +0000412 table->count++;
paul718e3742002-12-13 20:15:29 +0000413
hasso508e53e2004-05-18 18:57:06 +0000414 SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
415 if (table->hook_add)
416 (*table->hook_add) (route);
paul718e3742002-12-13 20:15:29 +0000417
hasso508e53e2004-05-18 18:57:06 +0000418 ospf6_route_count_assert (table);
419 return route;
paul718e3742002-12-13 20:15:29 +0000420}
421
422void
hasso508e53e2004-05-18 18:57:06 +0000423ospf6_route_remove (struct ospf6_route *route,
paul718e3742002-12-13 20:15:29 +0000424 struct ospf6_route_table *table)
425{
hasso508e53e2004-05-18 18:57:06 +0000426 struct route_node *node;
427 struct ospf6_route *current;
428 char buf[64];
paul718e3742002-12-13 20:15:29 +0000429
hasso508e53e2004-05-18 18:57:06 +0000430 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
431 ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
432 else
433 prefix2str (&route->prefix, buf, sizeof (buf));
paul718e3742002-12-13 20:15:29 +0000434
hasso508e53e2004-05-18 18:57:06 +0000435 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
436 zlog_info ("route remove: %s", buf);
437
438 node = route_node_lookup (table->table, &route->prefix);
439 assert (node);
440
441 /* find the route to remove, making sure that the route pointer
442 is from the route table. */
443 current = node->info;
444 while (current && ospf6_route_is_same (current, route))
paul718e3742002-12-13 20:15:29 +0000445 {
hasso508e53e2004-05-18 18:57:06 +0000446 if (current == route)
447 break;
448 current = current->next;
449 }
450 assert (current == route);
451
452 /* adjust doubly linked list */
453 if (route->prev)
454 route->prev->next = route->next;
455 if (route->next)
456 route->next->prev = route->prev;
457
458 if (node->info == route)
459 {
460 if (route->next && ospf6_route_is_same (route->next, route))
paul718e3742002-12-13 20:15:29 +0000461 {
hasso508e53e2004-05-18 18:57:06 +0000462 node->info = route->next;
463 SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
paul718e3742002-12-13 20:15:29 +0000464 }
hasso508e53e2004-05-18 18:57:06 +0000465 else
466 node->info = NULL; /* should unlock route_node here ? */
paul718e3742002-12-13 20:15:29 +0000467 }
468
paul718e3742002-12-13 20:15:29 +0000469 if (table->hook_remove)
hasso508e53e2004-05-18 18:57:06 +0000470 (*table->hook_remove) (route);
paul718e3742002-12-13 20:15:29 +0000471
hasso508e53e2004-05-18 18:57:06 +0000472 ospf6_route_unlock (route);
473 table->count--;
paul718e3742002-12-13 20:15:29 +0000474
hasso508e53e2004-05-18 18:57:06 +0000475 ospf6_route_count_assert (table);
476}
paul718e3742002-12-13 20:15:29 +0000477
hasso508e53e2004-05-18 18:57:06 +0000478struct ospf6_route *
479ospf6_route_head (struct ospf6_route_table *table)
480{
481 struct route_node *node;
482 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000483
hasso508e53e2004-05-18 18:57:06 +0000484 node = route_top (table->table);
485 if (node == NULL)
486 return NULL;
487
488 /* skip to the real existing entry */
489 while (node && node->info == NULL)
490 node = route_next (node);
491 if (node == NULL)
492 return NULL;
493
494 route_unlock_node (node);
495 assert (node->info);
496
497 route = (struct ospf6_route *) node->info;
498 assert (route->prev == NULL);
499 ospf6_route_lock (route);
500 return route;
501}
502
503struct ospf6_route *
504ospf6_route_next (struct ospf6_route *route)
505{
506 struct ospf6_route *next = route->next;
507
508 ospf6_route_unlock (route);
509 if (next)
510 ospf6_route_lock (next);
511
512 return next;
513}
514
515struct ospf6_route *
516ospf6_route_best_next (struct ospf6_route *route)
517{
518 struct route_node *rnode;
519 struct ospf6_route *next;
520
521 rnode = route->rnode;
522 route_lock_node (rnode);
523 rnode = route_next (rnode);
524 while (rnode && rnode->info == NULL)
525 rnode = route_next (rnode);
526 if (rnode == NULL)
527 return NULL;
528 route_unlock_node (rnode);
529
530 assert (rnode->info);
531 next = (struct ospf6_route *) rnode->info;
532 ospf6_route_unlock (route);
533 ospf6_route_lock (next);
534 return next;
535}
536
537/* Macro version of check_bit (). */
538#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
539
540struct ospf6_route *
541ospf6_route_match_head (struct prefix *prefix,
542 struct ospf6_route_table *table)
543{
544 struct route_node *node;
545 struct ospf6_route *route;
546
547 /* Walk down tree. */
548 node = table->table->top;
549 while (node && node->p.prefixlen < prefix->prefixlen &&
550 prefix_match (&node->p, prefix))
551 node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
552
553 if (node)
554 route_lock_node (node);
555 while (node && node->info == NULL)
556 node = route_next (node);
557 if (node == NULL)
558 return NULL;
559 route_unlock_node (node);
560
561 if (! prefix_match (prefix, &node->p))
562 return NULL;
563
564 route = node->info;
565 ospf6_route_lock (route);
566 return route;
567}
568
569struct ospf6_route *
570ospf6_route_match_next (struct prefix *prefix,
571 struct ospf6_route *route)
572{
573 struct ospf6_route *next;
574
575 next = ospf6_route_next (route);
576 if (next && ! prefix_match (prefix, &next->prefix))
577 {
578 ospf6_route_unlock (next);
579 next = NULL;
580 }
581
582 return next;
paul718e3742002-12-13 20:15:29 +0000583}
584
585void
586ospf6_route_remove_all (struct ospf6_route_table *table)
587{
hasso508e53e2004-05-18 18:57:06 +0000588 struct ospf6_route *route;
589 for (route = ospf6_route_head (table); route;
590 route = ospf6_route_next (route))
591 ospf6_route_remove (route, table);
paul718e3742002-12-13 20:15:29 +0000592}
593
paul718e3742002-12-13 20:15:29 +0000594struct ospf6_route_table *
hasso508e53e2004-05-18 18:57:06 +0000595ospf6_route_table_create ()
paul718e3742002-12-13 20:15:29 +0000596{
paul718e3742002-12-13 20:15:29 +0000597 struct ospf6_route_table *new;
paul718e3742002-12-13 20:15:29 +0000598 new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
paul718e3742002-12-13 20:15:29 +0000599 new->table = route_table_init ();
paul718e3742002-12-13 20:15:29 +0000600 return new;
601}
602
603void
604ospf6_route_table_delete (struct ospf6_route_table *table)
605{
paul718e3742002-12-13 20:15:29 +0000606 ospf6_route_remove_all (table);
607 route_table_finish (table->table);
paul718e3742002-12-13 20:15:29 +0000608 XFREE (MTYPE_OSPF6_ROUTE, table);
609}
610
paul718e3742002-12-13 20:15:29 +0000611
612
613/* VTY commands */
hasso508e53e2004-05-18 18:57:06 +0000614void
615ospf6_route_show (struct vty *vty, struct ospf6_route *route)
616{
617 int i;
618 char destination[64], nexthop[64];
619 char duration[16], ifname[IFNAMSIZ];
620 struct timeval now, res;
621
622 gettimeofday (&now, (struct timezone *) NULL);
623 timersub (&now, &route->changed, &res);
624 timerstring (&res, duration, sizeof (duration));
625
626 /* destination */
627 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
628 ospf6_linkstate_prefix2str (&route->prefix, destination,
629 sizeof (destination));
630 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
631 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
632 destination, sizeof (destination));
633 else
634 prefix2str (&route->prefix, destination, sizeof (destination));
635
636 /* nexthop */
637 inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
638 sizeof (nexthop));
639 if (! if_indextoname (route->nexthop[0].ifindex, ifname))
640 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
641
642 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
643 (ospf6_route_is_best (route) ? '*' : ' '),
644 OSPF6_DEST_TYPE_SUBSTR (route->type),
645 OSPF6_PATH_TYPE_SUBSTR (route->path.type),
hasso049207c2004-08-04 20:02:13 +0000646 destination, nexthop, ifname, duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000647
648 for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
649 i < OSPF6_MULTI_PATH_LIMIT; i++)
650 {
651 /* nexthop */
652 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
653 sizeof (nexthop));
654 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
655 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
656
657 vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
hasso049207c2004-08-04 20:02:13 +0000658 ' ', "", "", "", nexthop, ifname, "", VNL);
hasso508e53e2004-05-18 18:57:06 +0000659 }
660}
paul718e3742002-12-13 20:15:29 +0000661
662void
hasso508e53e2004-05-18 18:57:06 +0000663ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
paul718e3742002-12-13 20:15:29 +0000664{
hasso508e53e2004-05-18 18:57:06 +0000665 char destination[64], nexthop[64], ifname[IFNAMSIZ];
666 char area_id[16], id[16], adv_router[16], capa[16], options[16];
paul718e3742002-12-13 20:15:29 +0000667 struct timeval now, res;
668 char duration[16];
hasso508e53e2004-05-18 18:57:06 +0000669 int i;
paul718e3742002-12-13 20:15:29 +0000670
671 gettimeofday (&now, (struct timezone *) NULL);
672
673 /* destination */
hasso508e53e2004-05-18 18:57:06 +0000674 if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
675 ospf6_linkstate_prefix2str (&route->prefix, destination,
676 sizeof (destination));
677 else if (route->type == OSPF6_DEST_TYPE_ROUTER)
678 inet_ntop (route->prefix.family, &route->prefix.u.prefix,
679 destination, sizeof (destination));
paul718e3742002-12-13 20:15:29 +0000680 else
hasso508e53e2004-05-18 18:57:06 +0000681 prefix2str (&route->prefix, destination, sizeof (destination));
hasso049207c2004-08-04 20:02:13 +0000682 vty_out (vty, "Destination: %s%s", destination, VNL);
paul718e3742002-12-13 20:15:29 +0000683
hasso508e53e2004-05-18 18:57:06 +0000684 /* destination type */
685 vty_out (vty, "Destination type: %s%s",
686 OSPF6_DEST_TYPE_NAME (route->type),
hasso049207c2004-08-04 20:02:13 +0000687 VNL);
hasso508e53e2004-05-18 18:57:06 +0000688
689 /* Time */
690 timersub (&now, &route->installed, &res);
691 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000692 vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000693
694 timersub (&now, &route->changed, &res);
695 timerstring (&res, duration, sizeof (duration));
hasso049207c2004-08-04 20:02:13 +0000696 vty_out (vty, " Changed Time: %s ago%s", duration, VNL);
hasso508e53e2004-05-18 18:57:06 +0000697
698 /* Debugging info */
699 vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
700 (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
701 (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
702 (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
703 (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
hasso049207c2004-08-04 20:02:13 +0000704 VNL);
hasso508e53e2004-05-18 18:57:06 +0000705 vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000706 route->prev, route, route->next, VNL);
hasso508e53e2004-05-18 18:57:06 +0000707
708 /* Path section */
709
710 /* Area-ID */
711 inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
hasso049207c2004-08-04 20:02:13 +0000712 vty_out (vty, "Associated Area: %s%s", area_id, VNL);
hasso508e53e2004-05-18 18:57:06 +0000713
714 /* Path type */
715 vty_out (vty, "Path Type: %s%s",
hasso049207c2004-08-04 20:02:13 +0000716 OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
hasso508e53e2004-05-18 18:57:06 +0000717
718 /* LS Origin */
719 inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
720 inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
721 sizeof (adv_router));
722 vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
723 OSPF6_LSTYPE_NAME (route->path.origin.type),
hasso049207c2004-08-04 20:02:13 +0000724 id, adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000725
726 /* Options */
727 ospf6_options_printbuf (route->path.options, options, sizeof (options));
hasso049207c2004-08-04 20:02:13 +0000728 vty_out (vty, "Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000729
730 /* Router Bits */
731 ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
hasso049207c2004-08-04 20:02:13 +0000732 vty_out (vty, "Router Bits: %s%s", capa, VNL);
hasso508e53e2004-05-18 18:57:06 +0000733
734 /* Prefix Options */
hasso049207c2004-08-04 20:02:13 +0000735 vty_out (vty, "Prefix Options: xxx%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000736
737 /* Metrics */
738 vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
hasso049207c2004-08-04 20:02:13 +0000739 VNL);
hasso508e53e2004-05-18 18:57:06 +0000740 vty_out (vty, "Metric: %d (%d)%s",
hasso049207c2004-08-04 20:02:13 +0000741 route->path.cost, route->path.cost_e2, VNL);
hasso508e53e2004-05-18 18:57:06 +0000742
743 /* Nexthops */
hasso049207c2004-08-04 20:02:13 +0000744 vty_out (vty, "Nexthop:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000745 for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
746 i < OSPF6_MULTI_PATH_LIMIT; i++)
paul718e3742002-12-13 20:15:29 +0000747 {
hasso508e53e2004-05-18 18:57:06 +0000748 /* nexthop */
749 inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
750 sizeof (nexthop));
751 if (! if_indextoname (route->nexthop[i].ifindex, ifname))
752 snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
hasso049207c2004-08-04 20:02:13 +0000753 vty_out (vty, " %s %s%s", nexthop, ifname, VNL);
paul718e3742002-12-13 20:15:29 +0000754 }
hasso049207c2004-08-04 20:02:13 +0000755 vty_out (vty, "%s", VNL);
paul718e3742002-12-13 20:15:29 +0000756}
757
758void
hasso508e53e2004-05-18 18:57:06 +0000759ospf6_route_show_table_summary (struct vty *vty,
760 struct ospf6_route_table *table)
paul718e3742002-12-13 20:15:29 +0000761{
hasso508e53e2004-05-18 18:57:06 +0000762 struct ospf6_route *route, *prev = NULL;
763 int i, pathtype[OSPF6_PATH_TYPE_MAX];
764 int number = 0;
765 int nhinval = 0, ecmp = 0;
766 int multipath = 0, destination = 0;
767 int desttype = 0, desttype_mismatch = 0;
paul718e3742002-12-13 20:15:29 +0000768
hasso508e53e2004-05-18 18:57:06 +0000769 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
770 pathtype[i] = 0;
paul718e3742002-12-13 20:15:29 +0000771
hasso508e53e2004-05-18 18:57:06 +0000772 for (route = ospf6_route_head (table); route;
773 route = ospf6_route_next (route))
paul718e3742002-12-13 20:15:29 +0000774 {
hasso508e53e2004-05-18 18:57:06 +0000775 if (desttype == 0)
776 desttype = route->type;
777 else if (desttype != route->type)
778 desttype_mismatch++;
paul718e3742002-12-13 20:15:29 +0000779
hasso508e53e2004-05-18 18:57:06 +0000780 if (prev == NULL || ! ospf6_route_is_same (prev, route))
781 destination++;
782 else
783 multipath++;
paul718e3742002-12-13 20:15:29 +0000784
hasso508e53e2004-05-18 18:57:06 +0000785 if (! ospf6_nexthop_is_set (&route->nexthop[0]))
786 nhinval++;
787 else if (ospf6_nexthop_is_set (&route->nexthop[1]))
788 ecmp++;
paul718e3742002-12-13 20:15:29 +0000789
hasso508e53e2004-05-18 18:57:06 +0000790 if (prev == NULL || ! ospf6_route_is_same (prev, route))
791 pathtype[route->path.type]++;
paul718e3742002-12-13 20:15:29 +0000792
hasso508e53e2004-05-18 18:57:06 +0000793 number++;
794 prev = route;
paul718e3742002-12-13 20:15:29 +0000795 }
hasso508e53e2004-05-18 18:57:06 +0000796
797 assert (number == table->count);
798 vty_out (vty, "Number of Destination: %d (%d routes)%s",
hasso049207c2004-08-04 20:02:13 +0000799 destination, number, VNL);
hasso508e53e2004-05-18 18:57:06 +0000800 if (multipath)
hasso049207c2004-08-04 20:02:13 +0000801 vty_out (vty, " Number of Multi-path: %d%s", multipath, VNL);
hasso508e53e2004-05-18 18:57:06 +0000802 if (desttype_mismatch)
803 vty_out (vty, " Number of Different Dest-type: %d%s",
hasso049207c2004-08-04 20:02:13 +0000804 desttype_mismatch, VNL);
hasso508e53e2004-05-18 18:57:06 +0000805 if (ecmp)
806 vty_out (vty, " Number of Equal Cost Multi Path: %d%s",
hasso049207c2004-08-04 20:02:13 +0000807 ecmp, VNL);
hasso508e53e2004-05-18 18:57:06 +0000808 if (ecmp)
809 vty_out (vty, " Number of Invalid Nexthop: %d%s",
hasso049207c2004-08-04 20:02:13 +0000810 nhinval, VNL);
hasso508e53e2004-05-18 18:57:06 +0000811
812 for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
813 {
814 if (pathtype[i])
815 vty_out (vty, " Number of %s routes: %d%s",
hasso049207c2004-08-04 20:02:13 +0000816 OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000817 }
paul718e3742002-12-13 20:15:29 +0000818}
819
820int
821ospf6_route_table_show (struct vty *vty, int argc, char **argv,
822 struct ospf6_route_table *table)
823{
hasso508e53e2004-05-18 18:57:06 +0000824 unsigned char flag = 0;
825#define MATCH 0x01
826#define DETAIL 0x02
827#define PREFIX 0x04
828#define SUMMARY 0x08
paul718e3742002-12-13 20:15:29 +0000829 int i, ret;
hasso508e53e2004-05-18 18:57:06 +0000830 struct prefix prefix, *p;
831 struct ospf6_route *route;
paul718e3742002-12-13 20:15:29 +0000832
833 memset (&prefix, 0, sizeof (struct prefix));
834
835 for (i = 0; i < argc; i++)
836 {
hasso508e53e2004-05-18 18:57:06 +0000837 /* set "detail" */
838 if (! strcmp (argv[i], "summary"))
839 {
840 SET_FLAG (flag, SUMMARY);
841 continue;
842 }
843
844 /* set "detail" */
paul718e3742002-12-13 20:15:29 +0000845 if (! strcmp (argv[i], "detail"))
846 {
hasso508e53e2004-05-18 18:57:06 +0000847 SET_FLAG (flag, DETAIL);
848 continue;
paul718e3742002-12-13 20:15:29 +0000849 }
850
hasso508e53e2004-05-18 18:57:06 +0000851 /* set "match" */
852 if (! strcmp (argv[i], "match"))
paul718e3742002-12-13 20:15:29 +0000853 {
hasso508e53e2004-05-18 18:57:06 +0000854 SET_FLAG (flag, MATCH);
855 continue;
paul718e3742002-12-13 20:15:29 +0000856 }
857
hasso508e53e2004-05-18 18:57:06 +0000858 if (prefix.family)
paul718e3742002-12-13 20:15:29 +0000859 {
hasso049207c2004-08-04 20:02:13 +0000860 vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000861 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000862 }
hasso508e53e2004-05-18 18:57:06 +0000863
864 ret = str2prefix (argv[i], &prefix);
865 if (ret != 1 || prefix.family != AF_INET6)
866 {
hasso049207c2004-08-04 20:02:13 +0000867 vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000868 return CMD_SUCCESS;
869 }
870
871 if (strchr (argv[i], '/'))
872 SET_FLAG (flag, PREFIX);
paul718e3742002-12-13 20:15:29 +0000873 }
874
hasso508e53e2004-05-18 18:57:06 +0000875 /* Give summary of this route table */
876 if (CHECK_FLAG (flag, SUMMARY))
paul718e3742002-12-13 20:15:29 +0000877 {
hasso508e53e2004-05-18 18:57:06 +0000878 ospf6_route_show_table_summary (vty, table);
paul718e3742002-12-13 20:15:29 +0000879 return CMD_SUCCESS;
880 }
881
hasso508e53e2004-05-18 18:57:06 +0000882 /* Give exact prefix-match route */
883 if (prefix.family && ! CHECK_FLAG (flag, MATCH))
paul718e3742002-12-13 20:15:29 +0000884 {
hasso508e53e2004-05-18 18:57:06 +0000885 /* If exact address, give best matching route */
886 if (! CHECK_FLAG (flag, PREFIX))
887 route = ospf6_route_lookup_bestmatch (&prefix, table);
888 else
889 route = ospf6_route_lookup (&prefix, table);
890
891 if (route)
892 {
893 ospf6_route_lock (route);
894 p = &route->prefix;
895 }
896
897 while (route && ospf6_route_is_prefix (p, route))
898 {
899 /* Seaching an entry will always display details */
900 if (route)
901 ospf6_route_show_detail (vty, route);
902
903 route = ospf6_route_next (route);
904 }
905
906 return CMD_SUCCESS;
paul718e3742002-12-13 20:15:29 +0000907 }
908
hasso508e53e2004-05-18 18:57:06 +0000909 if (prefix.family == 0)
910 route = ospf6_route_head (table);
911 else
912 route = ospf6_route_match_head (&prefix, table);
913
914 while (route)
paul718e3742002-12-13 20:15:29 +0000915 {
hasso508e53e2004-05-18 18:57:06 +0000916 if (CHECK_FLAG (flag, DETAIL))
paul718e3742002-12-13 20:15:29 +0000917 ospf6_route_show_detail (vty, route);
918 else
919 ospf6_route_show (vty, route);
920
hasso508e53e2004-05-18 18:57:06 +0000921 if (prefix.family == 0)
922 route = ospf6_route_next (route);
923 else
924 route = ospf6_route_match_next (&prefix, route);
paul718e3742002-12-13 20:15:29 +0000925 }
926
paul718e3742002-12-13 20:15:29 +0000927 return CMD_SUCCESS;
928}
929
hasso508e53e2004-05-18 18:57:06 +0000930
931int
932ospf6_lsentry_table_show (struct vty *vty, int argc, char **argv,
933 struct ospf6_route_table *table)
934{
935 unsigned char flag = 0;
936#define MATCH 0x01
937#define DETAIL 0x02
938 int i, ret;
939 struct prefix adv_router, id, prefix;
940 struct ospf6_route *route;
941
942 memset (&adv_router, 0, sizeof (struct prefix));
943 memset (&id, 0, sizeof (struct prefix));
944
945 for (i = 0; i < argc; i++)
946 {
947 /* set "detail" */
948 if (! strcmp (argv[i], "detail"))
949 {
950 SET_FLAG (flag, DETAIL);
951 continue;
952 }
953
954 /* set "match" */
955 if (! strcmp (argv[i], "match"))
956 {
957 SET_FLAG (flag, MATCH);
958 continue;
959 }
960
961 if (adv_router.family && id.family)
962 {
hasso049207c2004-08-04 20:02:13 +0000963 vty_out (vty, "Invalid argument: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000964 return CMD_SUCCESS;
965 }
966
967 if (adv_router.family == 0)
968 {
969 ret = str2prefix (argv[i], &adv_router);
970 if (ret != 1)
971 {
972 if (! strcmp (argv[i], "*"))
973 {
974 adv_router.family = AF_INET;
975 adv_router.prefixlen = 0;
976 ret = 1;
977 }
978 }
979 if (ret != 1)
980 {
hasso049207c2004-08-04 20:02:13 +0000981 vty_out (vty, "Invalid Router-ID: %s%s", argv[i], VNL);
hasso508e53e2004-05-18 18:57:06 +0000982 return CMD_SUCCESS;
983 }
984 }
985 else if (id.family == 0)
986 {
987 unsigned long val;
988 char *endptr;
989
990 ret = str2prefix (argv[i], &id);
991 if (ret != 1)
992 {
993 val = strtoul (argv[i], &endptr, 0);
994 if (val != ULONG_MAX && *endptr == '\0')
995 {
996 id.u.prefix4.s_addr = val;
997 ret = 1;
998 }
999 }
1000
1001 if (ret != 1)
1002 {
1003 vty_out (vty, "Invalid Link state ID: %s%s", argv[i],
hasso049207c2004-08-04 20:02:13 +00001004 VNL);
hasso508e53e2004-05-18 18:57:06 +00001005 return CMD_WARNING;
1006 }
1007 }
1008 }
1009
1010 /* Encode to linkstate prefix */
1011 if (adv_router.family)
1012 {
1013 if (adv_router.prefixlen == 0 &&
1014 id.family && id.prefixlen != IPV4_MAX_BITLEN)
1015 {
1016 vty_out (vty, "Specifying Link State ID by prefix is not allowed%s"
1017 "when specifying Router-ID as wildcard%s",
hasso049207c2004-08-04 20:02:13 +00001018 VNL, VNL);
hasso508e53e2004-05-18 18:57:06 +00001019 return CMD_SUCCESS;
1020 }
1021 else if (adv_router.prefixlen != 0 &&
1022 adv_router.prefixlen != IPV4_MAX_BITLEN && id.family)
1023 {
1024 vty_out (vty, "Specifying Link State ID is not allowed%s"
1025 "when specifying Router-ID by prefix%s",
hasso049207c2004-08-04 20:02:13 +00001026 VNL, VNL);
hasso508e53e2004-05-18 18:57:06 +00001027 return CMD_SUCCESS;
1028 }
1029
1030 if (adv_router.prefixlen == 0)
1031 ospf6_linkstate_prefix (0, id.u.prefix4.s_addr, &prefix);
1032 else if (adv_router.prefixlen != IPV4_MAX_BITLEN)
1033 {
1034 ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr, 0, &prefix);
1035 prefix.prefixlen = adv_router.prefixlen;
1036 SET_FLAG (flag, MATCH);
1037 }
1038 else
1039 {
1040 ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr,
1041 id.u.prefix4.s_addr, &prefix);
1042 prefix.prefixlen = adv_router.prefixlen + id.prefixlen;
1043 if (prefix.prefixlen != 64)
1044 SET_FLAG (flag, MATCH);
1045 }
1046 }
1047
1048 /* give exact match entry */
1049 if (adv_router.family && adv_router.prefixlen == IPV4_MAX_BITLEN &&
1050 id.family && id.prefixlen == IPV4_MAX_BITLEN)
1051 {
1052 route = ospf6_route_lookup (&prefix, table);
1053 if (route)
1054 ospf6_route_show_detail (vty, route);
1055 return CMD_SUCCESS;
1056 }
1057
1058 if (CHECK_FLAG (flag, MATCH))
1059 route = ospf6_route_match_head (&prefix, table);
1060 else
1061 route = ospf6_route_head (table);
1062
1063 while (route)
1064 {
1065 if (! adv_router.family ||
1066 (CHECK_FLAG (flag, MATCH) &&
1067 prefix_match (&prefix, &route->prefix)) ||
1068 (adv_router.prefixlen == 0 && id.family &&
1069 ospf6_linkstate_prefix_id (&prefix) ==
1070 ospf6_linkstate_prefix_id (&route->prefix)))
1071 {
1072 if (CHECK_FLAG (flag, DETAIL))
1073 ospf6_route_show_detail (vty, route);
1074 else
1075 ospf6_route_show (vty, route);
1076 }
1077
1078 if (CHECK_FLAG (flag, MATCH))
1079 route = ospf6_route_match_next (&prefix, route);
1080 else
1081 route = ospf6_route_next (route);
1082 }
1083
1084 return CMD_SUCCESS;
1085}
1086
hasso6452df02004-08-15 05:52:07 +00001087void
1088ospf6_brouter_show_header (struct vty *vty)
1089{
1090 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1091 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL);
1092}
1093
1094void
1095ospf6_brouter_show (struct vty *vty, struct ospf6_route *route)
1096{
1097 u_int32_t adv_router;
1098 char adv[16], rbits[16], options[16], area[16];
1099
1100 adv_router = ospf6_linkstate_prefix_adv_router (&route->prefix);
1101 inet_ntop (AF_INET, &adv_router, adv, sizeof (adv));
1102 ospf6_capability_printbuf (route->path.router_bits, rbits, sizeof (rbits));
1103 ospf6_options_printbuf (route->path.options, options, sizeof (options));
1104 inet_ntop (AF_INET, &route->path.area_id, area, sizeof (area));
1105
1106 /* vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1107 "Router-ID", "Rtr-Bits", "Options", "Path-Type", "Area", VNL); */
1108 vty_out (vty, "%-15s %-8s %-14s %-10s %-15s%s",
1109 adv, rbits, options, OSPF6_PATH_TYPE_NAME (route->path.type),
1110 area, VNL);
1111}
1112
hasso508e53e2004-05-18 18:57:06 +00001113DEFUN (debug_ospf6_route,
1114 debug_ospf6_route_cmd,
1115 "debug ospf6 route (table|intra-area|inter-area)",
1116 DEBUG_STR
1117 OSPF6_STR
1118 "Debug route table calculation\n"
1119 "Debug detail\n"
1120 "Debug intra-area route calculation\n"
1121 "Debug inter-area route calculation\n"
1122 )
1123{
1124 unsigned char level = 0;
1125
1126 if (! strncmp (argv[0], "table", 5))
1127 level = OSPF6_DEBUG_ROUTE_TABLE;
1128 else if (! strncmp (argv[0], "intra", 5))
1129 level = OSPF6_DEBUG_ROUTE_INTRA;
1130 else if (! strncmp (argv[0], "inter", 5))
1131 level = OSPF6_DEBUG_ROUTE_INTER;
1132 OSPF6_DEBUG_ROUTE_ON (level);
1133 return CMD_SUCCESS;
1134}
1135
1136DEFUN (no_debug_ospf6_route,
1137 no_debug_ospf6_route_cmd,
1138 "no debug ospf6 route (table|intra-area|inter-area)",
1139 NO_STR
1140 DEBUG_STR
1141 OSPF6_STR
1142 "Debug route table calculation\n"
1143 "Debug intra-area route calculation\n")
1144{
1145 unsigned char level = 0;
1146
1147 if (! strncmp (argv[0], "table", 5))
1148 level = OSPF6_DEBUG_ROUTE_TABLE;
1149 else if (! strncmp (argv[0], "intra", 5))
1150 level = OSPF6_DEBUG_ROUTE_INTRA;
1151 else if (! strncmp (argv[0], "inter", 5))
1152 level = OSPF6_DEBUG_ROUTE_INTER;
1153 OSPF6_DEBUG_ROUTE_OFF (level);
1154 return CMD_SUCCESS;
1155}
1156
1157int
1158config_write_ospf6_debug_route (struct vty *vty)
1159{
1160 if (IS_OSPF6_DEBUG_ROUTE (TABLE))
hasso049207c2004-08-04 20:02:13 +00001161 vty_out (vty, "debug ospf6 route table%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001162 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
hasso049207c2004-08-04 20:02:13 +00001163 vty_out (vty, "debug ospf6 route intra-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001164 if (IS_OSPF6_DEBUG_ROUTE (INTER))
hasso049207c2004-08-04 20:02:13 +00001165 vty_out (vty, "debug ospf6 route inter-area%s", VNL);
hasso508e53e2004-05-18 18:57:06 +00001166 return 0;
1167}
1168
1169void
1170install_element_ospf6_debug_route ()
1171{
1172 install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
1173 install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
1174 install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
1175 install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
1176}
1177
1178
1179