~ubuntu-branches/ubuntu/breezy/quagga/breezy-security

« back to all changes in this revision

Viewing changes to ospf6d/ospf6_route.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-05-20 13:16:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050520131612-pr6paalox60o3x3n
Tags: upstream-0.99.1
ImportĀ upstreamĀ versionĀ 0.99.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003 Yasuhiro Ohara
 
3
 *
 
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
 
 
22
#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
 
 
31
#include "ospf6_proto.h"
 
32
#include "ospf6_lsa.h"
 
33
#include "ospf6_lsdb.h"
 
34
#include "ospf6_route.h"
 
35
#include "ospf6d.h"
 
36
 
 
37
unsigned char conf_debug_ospf6_route = 0;
 
38
 
 
39
void
 
40
ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
 
41
                        struct prefix *prefix)
 
42
{
 
43
  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);
 
48
}
 
49
 
 
50
void
 
51
ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
 
52
{
 
53
  u_int32_t adv_router, id;
 
54
  char adv_router_str[16], id_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
  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);
 
63
}
 
64
 
 
65
/* Global strings for logging */
 
66
const char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
 
67
{ "Unknown", "Router", "Network", "Discard", "Linkstate", "AddressRange", };
 
68
 
 
69
const char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
 
70
{ "?", "R", "N", "D", "L", "A", };
 
71
 
 
72
const char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
 
73
{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
 
74
 
 
75
const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
 
76
{ "??", "IA", "IE", "E1", "E2", };
 
77
 
 
78
 
 
79
struct ospf6_route *
 
80
ospf6_route_create ()
 
81
{
 
82
  struct ospf6_route *route;
 
83
  route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
 
84
  return route;
 
85
}
 
86
 
 
87
void
 
88
ospf6_route_delete (struct ospf6_route *route)
 
89
{
 
90
  XFREE (MTYPE_OSPF6_ROUTE, route);
 
91
}
 
92
 
 
93
struct ospf6_route *
 
94
ospf6_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
 
 
107
void
 
108
ospf6_route_lock (struct ospf6_route *route)
 
109
{
 
110
  route->lock++;
 
111
}
 
112
 
 
113
void
 
114
ospf6_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 */
 
125
static int
 
126
ospf6_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
 
 
157
struct ospf6_route *
 
158
ospf6_route_lookup (struct prefix *prefix,
 
159
                    struct ospf6_route_table *table)
 
160
{
 
161
  struct route_node *node;
 
162
  struct ospf6_route *route;
 
163
 
 
164
  node = route_node_lookup (table->table, prefix);
 
165
  if (node == NULL)
 
166
    return NULL;
 
167
 
 
168
  route = (struct ospf6_route *) node->info;
 
169
  return route;
 
170
}
 
171
 
 
172
struct ospf6_route *
 
173
ospf6_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
 
 
187
struct ospf6_route *
 
188
ospf6_route_lookup_bestmatch (struct prefix *prefix,
 
189
                              struct ospf6_route_table *table)
 
190
{
 
191
  struct route_node *node;
 
192
  struct ospf6_route *route;
 
193
 
 
194
  node = route_node_match (table->table, prefix);
 
195
  if (node == NULL)
 
196
    return NULL;
 
197
  route_unlock_node (node);
 
198
 
 
199
  route = (struct ospf6_route *) node->info;
 
200
  return route;
 
201
}
 
202
 
 
203
#ifndef NDEBUG
 
204
static void
 
205
_route_count_assert (struct ospf6_route_table *table)
 
206
{
 
207
  struct ospf6_route *debug;
 
208
  char buf[64];
 
209
  unsigned int num = 0;
 
210
  for (debug = ospf6_route_head (table); debug;
 
211
       debug = ospf6_route_next (debug))
 
212
    num++;
 
213
 
 
214
  if (num == table->count)
 
215
    return;
 
216
 
 
217
  zlog_debug ("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_debug ("%p %p %s", debug->prev, debug->next, buf);
 
224
    }
 
225
  zlog_debug ("DUMP END");
 
226
 
 
227
  assert (num == table->count);
 
228
}
 
229
#define ospf6_route_count_assert(t) (_route_count_assert (t))
 
230
#else
 
231
#define ospf6_route_count_assert(t) ((void) 0)
 
232
#endif /*NDEBUG*/
 
233
 
 
234
struct ospf6_route *
 
235
ospf6_route_add (struct ospf6_route *route,
 
236
                 struct ospf6_route_table *table)
 
237
{
 
238
  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;
 
243
 
 
244
  assert (route->rnode == NULL);
 
245
  assert (route->lock == 0);
 
246
  assert (route->next == NULL);
 
247
  assert (route->prev == NULL);
 
248
 
 
249
  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));
 
253
 
 
254
  if (IS_OSPF6_DEBUG_ROUTE (TABLE))
 
255
    zlog_debug ("route add %s", buf);
 
256
 
 
257
  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)
 
264
    {
 
265
      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;
 
278
    }
 
279
 
 
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_debug ("  identical route found, ignore");
 
287
 
 
288
          ospf6_route_delete (route);
 
289
          SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
 
290
          ospf6_route_count_assert (table);
 
291
 
 
292
          return old;
 
293
        }
 
294
 
 
295
      if (IS_OSPF6_DEBUG_ROUTE (TABLE))
 
296
        zlog_debug ("  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);
 
319
      ospf6_route_count_assert (table);
 
320
 
 
321
      if (table->hook_add)
 
322
        (*table->hook_add) (route);
 
323
 
 
324
      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_debug ("  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++;
 
358
      ospf6_route_count_assert (table);
 
359
 
 
360
      SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
 
361
      if (table->hook_add)
 
362
        (*table->hook_add) (route);
 
363
 
 
364
      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_debug ("  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;
 
388
  else
 
389
    {
 
390
      route_unlock_node (nextnode);
 
391
 
 
392
      next = nextnode->info;
 
393
      route->next = next;
 
394
      next->prev = route;
 
395
    }
 
396
 
 
397
  /* 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);
 
403
 
 
404
  /* set prev link */
 
405
  if (prevnode == NULL)
 
406
    route->prev = NULL;
 
407
  else
 
408
    {
 
409
      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;
 
416
    }
 
417
 
 
418
  table->count++;
 
419
  ospf6_route_count_assert (table);
 
420
 
 
421
  SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
 
422
  if (table->hook_add)
 
423
    (*table->hook_add) (route);
 
424
 
 
425
  return route;
 
426
}
 
427
 
 
428
void
 
429
ospf6_route_remove (struct ospf6_route *route,
 
430
                    struct ospf6_route_table *table)
 
431
{
 
432
  struct route_node *node;
 
433
  struct ospf6_route *current;
 
434
  char buf[64];
 
435
 
 
436
  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));
 
440
 
 
441
  if (IS_OSPF6_DEBUG_ROUTE (TABLE))
 
442
    zlog_debug ("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))
 
451
    {
 
452
      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))
 
467
        {
 
468
          node->info = route->next;
 
469
          SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
 
470
        }
 
471
      else
 
472
        node->info = NULL; /* should unlock route_node here ? */
 
473
    }
 
474
 
 
475
  table->count--;
 
476
  ospf6_route_count_assert (table);
 
477
 
 
478
  SET_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED);
 
479
 
 
480
  if (table->hook_remove)
 
481
    (*table->hook_remove) (route);
 
482
 
 
483
  ospf6_route_unlock (route);
 
484
}
 
485
 
 
486
struct ospf6_route *
 
487
ospf6_route_head (struct ospf6_route_table *table)
 
488
{
 
489
  struct route_node *node;
 
490
  struct ospf6_route *route;
 
491
 
 
492
  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
 
 
511
struct ospf6_route *
 
512
ospf6_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
 
 
523
struct ospf6_route *
 
524
ospf6_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
 
 
548
struct ospf6_route *
 
549
ospf6_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
 
 
577
struct ospf6_route *
 
578
ospf6_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;
 
591
}
 
592
 
 
593
void
 
594
ospf6_route_remove_all (struct ospf6_route_table *table)
 
595
{
 
596
  struct ospf6_route *route;
 
597
  for (route = ospf6_route_head (table); route;
 
598
       route = ospf6_route_next (route))
 
599
    ospf6_route_remove (route, table);
 
600
}
 
601
 
 
602
struct ospf6_route_table *
 
603
ospf6_route_table_create ()
 
604
{
 
605
  struct ospf6_route_table *new;
 
606
  new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
 
607
  new->table = route_table_init ();
 
608
  return new;
 
609
}
 
610
 
 
611
void
 
612
ospf6_route_table_delete (struct ospf6_route_table *table)
 
613
{
 
614
  ospf6_route_remove_all (table);
 
615
  route_table_finish (table->table);
 
616
  XFREE (MTYPE_OSPF6_ROUTE, table);
 
617
}
 
618
 
 
619
 
 
620
 
 
621
/* VTY commands */
 
622
void
 
623
ospf6_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 %6.*s %s%s",
 
651
           (ospf6_route_is_best (route) ? '*' : ' '),
 
652
           OSPF6_DEST_TYPE_SUBSTR (route->type),
 
653
           OSPF6_PATH_TYPE_SUBSTR (route->path.type),
 
654
           destination, nexthop, IFNAMSIZ, ifname, duration, VNL);
 
655
 
 
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 %6.*s %s%s",
 
666
               ' ', "", "", "", nexthop, IFNAMSIZ, ifname, "", VNL);
 
667
    }
 
668
}
 
669
 
 
670
void
 
671
ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
 
672
{
 
673
  char destination[64], nexthop[64], ifname[IFNAMSIZ];
 
674
  char area_id[16], id[16], adv_router[16], capa[16], options[16];
 
675
  struct timeval now, res;
 
676
  char duration[16];
 
677
  int i;
 
678
 
 
679
  gettimeofday (&now, (struct timezone *) NULL);
 
680
 
 
681
  /* destination */
 
682
  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));
 
688
  else
 
689
    prefix2str (&route->prefix, destination, sizeof (destination));
 
690
  vty_out (vty, "Destination: %s%s", destination, VNL);
 
691
 
 
692
  /* destination type */
 
693
  vty_out (vty, "Destination type: %s%s",
 
694
           OSPF6_DEST_TYPE_NAME (route->type),
 
695
           VNL);
 
696
 
 
697
  /* Time */
 
698
  timersub (&now, &route->installed, &res);
 
699
  timerstring (&res, duration, sizeof (duration));
 
700
  vty_out (vty, "Installed Time: %s ago%s", duration, VNL);
 
701
 
 
702
  timersub (&now, &route->changed, &res);
 
703
  timerstring (&res, duration, sizeof (duration));
 
704
  vty_out (vty, "  Changed Time: %s ago%s", duration, VNL);
 
705
 
 
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" : "-"),
 
712
           VNL);
 
713
  vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
 
714
           route->prev, route, route->next, VNL);
 
715
 
 
716
  /* Path section */
 
717
 
 
718
  /* Area-ID */
 
719
  inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
 
720
  vty_out (vty, "Associated Area: %s%s", area_id, VNL);
 
721
 
 
722
  /* Path type */
 
723
  vty_out (vty, "Path Type: %s%s",
 
724
           OSPF6_PATH_TYPE_NAME (route->path.type), VNL);
 
725
 
 
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",
 
731
           ospf6_lstype_name (route->path.origin.type),
 
732
           id, adv_router, VNL);
 
733
 
 
734
  /* Options */
 
735
  ospf6_options_printbuf (route->path.options, options, sizeof (options));
 
736
  vty_out (vty, "Options: %s%s", options, VNL);
 
737
 
 
738
  /* Router Bits */
 
739
  ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
 
740
  vty_out (vty, "Router Bits: %s%s", capa, VNL);
 
741
 
 
742
  /* Prefix Options */
 
743
  vty_out (vty, "Prefix Options: xxx%s", VNL);
 
744
 
 
745
  /* Metrics */
 
746
  vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
 
747
           VNL);
 
748
  vty_out (vty, "Metric: %d (%d)%s",
 
749
           route->path.cost, route->path.cost_e2, VNL);
 
750
 
 
751
  /* Nexthops */
 
752
  vty_out (vty, "Nexthop:%s", VNL);
 
753
  for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
 
754
       i < OSPF6_MULTI_PATH_LIMIT; i++)
 
755
    {
 
756
      /* 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);
 
761
      vty_out (vty, "  %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL);
 
762
    }
 
763
  vty_out (vty, "%s", VNL);
 
764
}
 
765
 
 
766
void
 
767
ospf6_route_show_table_summary (struct vty *vty,
 
768
                                struct ospf6_route_table *table)
 
769
{
 
770
  struct ospf6_route *route, *prev = NULL;
 
771
  int i, pathtype[OSPF6_PATH_TYPE_MAX];
 
772
  unsigned int number = 0;
 
773
  int nhinval = 0, ecmp = 0;
 
774
  int alternative = 0, destination = 0;
 
775
 
 
776
  for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
 
777
    pathtype[i] = 0;
 
778
 
 
779
  for (route = ospf6_route_head (table); route;
 
780
       route = ospf6_route_next (route))
 
781
    {
 
782
      if (prev == NULL || ! ospf6_route_is_same (prev, route))
 
783
        destination++;
 
784
      else
 
785
        alternative++;
 
786
      if (! ospf6_nexthop_is_set (&route->nexthop[0]))
 
787
        nhinval++;
 
788
      else if (ospf6_nexthop_is_set (&route->nexthop[1]))
 
789
        ecmp++;
 
790
      pathtype[route->path.type]++;
 
791
      number++;
 
792
 
 
793
      prev = route;
 
794
    }
 
795
 
 
796
  assert (number == table->count);
 
797
 
 
798
  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++)
 
803
    {
 
804
      vty_out (vty, "Number of %s routes: %d%s",
 
805
               OSPF6_PATH_TYPE_NAME (i), pathtype[i], VNL);
 
806
    }
 
807
}
 
808
 
 
809
void
 
810
ospf6_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
 
 
831
void
 
832
ospf6_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
 
 
854
void
 
855
ospf6_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
 
 
873
void
 
874
ospf6_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
 
 
893
void
 
894
ospf6_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);
 
907
    }
 
908
}
 
909
 
 
910
int
 
911
ospf6_route_table_show (struct vty *vty, int argc, const char *argv[],
 
912
                        struct ospf6_route_table *table)
 
913
{
 
914
  int summary = 0;
 
915
  int match = 0;
 
916
  int detail = 0;
 
917
  int slash = 0;
 
918
  int isprefix = 0;
 
919
  int i, ret;
 
920
  struct prefix prefix;
 
921
  u_char type = 0;
 
922
 
 
923
  memset (&prefix, 0, sizeof (struct prefix));
 
924
 
 
925
  for (i = 0; i < argc; i++)
 
926
    {
 
927
      if (! strcmp (argv[i], "summary"))
 
928
        {
 
929
          summary++;
 
930
          continue;
 
931
        }
 
932
 
 
933
      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
 
 
957
      if (! strcmp (argv[i], "detail"))
 
958
        {
 
959
          detail++;
 
960
          continue;
 
961
        }
 
962
 
 
963
      if (! strcmp (argv[i], "match"))
 
964
        {
 
965
          match++;
 
966
          continue;
 
967
        }
 
968
 
 
969
      ret = str2prefix (argv[i], &prefix);
 
970
      if (ret == 1 && prefix.family == AF_INET6)
 
971
        {
 
972
          isprefix++;
 
973
          if (strchr (argv[i], '/'))
 
974
            slash++;
 
975
          continue;
 
976
        }
 
977
 
 
978
      vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
 
979
      return CMD_SUCCESS;
 
980
    }
 
981
 
 
982
  /* Give summary of this route table */
 
983
  if (summary)
 
984
    {
 
985
      ospf6_route_show_table_summary (vty, table);
 
986
      return CMD_SUCCESS;
 
987
    }
 
988
 
 
989
  /* Give exact prefix-match route */
 
990
  if (isprefix && ! match)
 
991
    {
 
992
      /* If exact address, give best matching route */
 
993
      if (! slash)
 
994
        ospf6_route_show_table_address (vty, &prefix, table);
 
995
      else
 
996
        ospf6_route_show_table_prefix (vty, &prefix, table);
 
997
 
 
998
      return CMD_SUCCESS;
 
999
    }
 
1000
 
 
1001
  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);
 
1005
  else
 
1006
    ospf6_route_show_table (vty, detail, table);
 
1007
 
 
1008
  return CMD_SUCCESS;
 
1009
}
 
1010
 
 
1011
void
 
1012
ospf6_linkstate_show_header (struct vty *vty)
 
1013
{
 
1014
  vty_out (vty, "%-7s %-15s %-15s %-8s %-14s %s%s",
 
1015
           "Type", "Router-ID", "Net-ID", "Rtr-Bits", "Options", "Cost", VNL);
 
1016
}
 
1017
 
 
1018
void
 
1019
ospf6_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
 
 
1043
void
 
1044
ospf6_linkstate_show_table_exact (struct vty *vty,
 
1045
                                  struct prefix *prefix,
 
1046
                                  struct ospf6_route_table *table)
 
1047
{
 
1048
  struct ospf6_route *route;
 
1049
 
 
1050
  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
 
 
1065
void
 
1066
ospf6_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
 
 
1085
int
 
1086
ospf6_linkstate_table_show (struct vty *vty, int argc, const char *argv[],
 
1087
                            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));
 
1096
  memset (&id, 0, sizeof (struct prefix));
 
1097
  memset (&prefix, 0, sizeof (struct prefix));
 
1098
 
 
1099
  for (i = 0; i < argc; i++)
 
1100
    {
 
1101
      if (! strcmp (argv[i], "detail"))
 
1102
        {
 
1103
          detail++;
 
1104
          continue;
 
1105
        }
 
1106
 
 
1107
      if (! is_router)
 
1108
        {
 
1109
          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);
 
1116
          return CMD_SUCCESS;
 
1117
        }
 
1118
 
 
1119
      if (! is_id)
 
1120
        {
 
1121
          ret = str2prefix (argv[i], &id);
 
1122
          if (ret == 1 && id.family == AF_INET)
 
1123
            {
 
1124
              is_id++;
 
1125
              continue;
 
1126
            }
 
1127
          vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
 
1128
          return CMD_SUCCESS;
 
1129
        }
 
1130
 
 
1131
      vty_out (vty, "Malformed argument: %s%s", argv[i], VNL);
 
1132
      return CMD_SUCCESS;
 
1133
    }
 
1134
 
 
1135
  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);
 
1141
  else
 
1142
    ospf6_linkstate_show_table (vty, detail, table);
 
1143
 
 
1144
  return CMD_SUCCESS;
 
1145
}
 
1146
 
 
1147
 
 
1148
void
 
1149
ospf6_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
 
 
1155
void
 
1156
ospf6_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
 
 
1174
DEFUN (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
 
 
1197
DEFUN (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
 
 
1218
int
 
1219
config_write_ospf6_debug_route (struct vty *vty)
 
1220
{
 
1221
  if (IS_OSPF6_DEBUG_ROUTE (TABLE))
 
1222
    vty_out (vty, "debug ospf6 route table%s", VNL);
 
1223
  if (IS_OSPF6_DEBUG_ROUTE (INTRA))
 
1224
    vty_out (vty, "debug ospf6 route intra-area%s", VNL);
 
1225
  if (IS_OSPF6_DEBUG_ROUTE (INTER))
 
1226
    vty_out (vty, "debug ospf6 route inter-area%s", VNL);
 
1227
  return 0;
 
1228
}
 
1229
 
 
1230
void
 
1231
install_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