blob: 40cf798d1dd02e37affd3dff7b2178644ab538e9 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * OSPF flap dampening by Manav Bhatia
3 * Copyright (C) 2002
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING. If not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 */
22
23#include <zebra.h>
24#include <math.h>
25
26#include "log.h"
27#include "prefix.h"
28#include "thread.h"
29#include "table.h"
30#include "command.h"
31#include "vty.h"
32
33extern struct thread_master *master;
34
35#include "ospf6_damp.h"
36
37#ifdef HAVE_OSPF6_DAMP
38
39#define DELTA_REUSE 10 /* Time granularity for reuse lists */
40#define DELTA_T 5 /* Time granularity for decay arrays */
41#define DEFAULT_HALF_LIFE 60 /* (sec) 1 min */
42
43#define DEFAULT_PENALTY 1000
44#define DEFAULT_REUSE 750
45#define DEFAULT_SUPPRESS 2000
46
47#define REUSE_LIST_SIZE 256
48#define REUSE_ARRAY_SIZE 1024
49
50/* Global variable to access damping configuration */
51struct ospf6_damp_config damp_config;
52struct ospf6_damp_config *dc = &damp_config;
53u_int reuse_array_offset = 0;
54struct route_table *damp_info_table[OSPF6_DAMP_TYPE_MAX];
55struct thread *ospf6_reuse_thread = NULL;
56
57int ospf6_damp_debug = 0;
58#define IS_OSPF6_DEBUG_DAMP (ospf6_damp_debug)
59
60static struct ospf6_damp_info *
61ospf6_damp_lookup (u_short type, struct prefix *name)
62{
63 struct route_node *node;
64
65 node = route_node_lookup (damp_info_table[type], name);
66 if (node && node->info)
67 return (struct ospf6_damp_info *) node->info;
68 return NULL;
69}
70
71static struct ospf6_damp_info *
72ospf6_damp_create (u_short type, struct prefix *name)
73{
74 struct route_node *node;
75 struct ospf6_damp_info *di;
76 char namebuf[64];
77
78 di = ospf6_damp_lookup (type, name);
79 if (di)
80 return di;
81
82 if (IS_OSPF6_DEBUG_DAMP)
83 {
84 prefix2str (name, namebuf, sizeof (namebuf));
85 zlog_info ("DAMP: create: type: %d, name: %s", type, namebuf);
86 }
87
88 di = (struct ospf6_damp_info *)
89 malloc (sizeof (struct ospf6_damp_info));
90 memset (di, 0, sizeof (struct ospf6_damp_info));
91 di->type = type;
92 prefix_copy (&di->name, name);
93
94 node = route_node_get (damp_info_table[type], name);
95 node->info = di;
96
97 return di;
98}
99
100static void
101ospf6_damp_delete (u_short type, struct prefix *name)
102{
103 struct route_node *node;
104 struct ospf6_damp_info *di;
105 char namebuf[64];
106
107 node = route_node_lookup (damp_info_table[type], name);
108 if (! node || ! node->info)
109 return;
110
111 di = node->info;
112
113 if (IS_OSPF6_DEBUG_DAMP)
114 {
115 prefix2str (&di->name, namebuf, sizeof (namebuf));
116 zlog_info ("DAMP: delete: type: %d, name: %s",
117 di->type, namebuf);
118 }
119
120 node->info = NULL;
121 free (di);
122}
123
124/* compute and fill the configuration parameter */
125void
126ospf6_damp_init_config (u_int half_life, u_int reuse,
127 u_int suppress, u_int t_hold)
128{
129 int i;
130 double max_ratio, max_ratio1, max_ratio2;
131
132 dc->half_life = half_life ? half_life : DEFAULT_HALF_LIFE;
133 dc->reuse = reuse ? reuse : DEFAULT_REUSE;
134 dc->suppress = suppress ? suppress : DEFAULT_SUPPRESS;
135 dc->t_hold = t_hold ? t_hold : 4 * dc->half_life;
136
137 /* Initialize system-wide params */
138 dc->delta_t = DELTA_T;
139 dc->delta_reuse = DELTA_REUSE;
140 dc->default_penalty = DEFAULT_PENALTY;
141 dc->reuse_index_array_size = REUSE_ARRAY_SIZE;
142
143 /* ceiling is the maximum penalty a route may attain */
144 /* ceiling = reuse * 2^(T-hold/half-life) */
145 dc->ceiling = (int)
146 (dc->reuse * (pow (2, (double) dc->t_hold / dc->half_life)));
147
148 /* Decay-array computations */
149 /* decay_array_size = decay memory/time granularity */
150 dc->decay_array_size = ceil ((double) dc->t_hold / dc->delta_t);
151 dc->decay_array = malloc (sizeof (double) * (dc->decay_array_size));
152
153 /* Each i-th element is per tick delay raised to the i-th power */
154 dc->decay_array[0] = 1.0;
155 dc->decay_array[1] = exp ((1.0 / (dc->half_life / dc->delta_t)) * log (0.5));
156 for (i = 2; i < dc->decay_array_size; i++)
157 dc->decay_array[i] = dc->decay_array[i - 1] * dc->decay_array[1];
158
159 /* Reuse-list computations (reuse queue head array ?) */
160 dc->reuse_list_size = ceil ((double) dc->t_hold / dc->delta_reuse) + 1;
161 if (dc->reuse_list_size == 0 || dc->reuse_list_size > REUSE_LIST_SIZE)
162 dc->reuse_list_size = REUSE_LIST_SIZE;
163 dc->reuse_list_array = (struct ospf6_damp_info **)
164 malloc (dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
165 memset (dc->reuse_list_array, 0x00,
166 dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
167
168 /* Reuse-array computations */
169 dc->reuse_index_array = malloc (sizeof (int) * dc->reuse_index_array_size);
170
171 /*
172 * This is the maximum ratio between the current value of the penalty and
173 * the reuse value which can be indexed by the reuse array. It will be
174 * limited by the ceiling or by the amount of time that the reuse list
175 * covers
176 */
177 max_ratio1 = (double) dc->ceiling / dc->reuse;
178 max_ratio2 = exp ((double) dc->t_hold / dc->half_life) * log10 (2.0);
179 max_ratio = (max_ratio2 != 0 && max_ratio2 < max_ratio1 ?
180 max_ratio2 : max_ratio1);
181
182 /*
183 * reuse array is just an estimator and we need something
184 * to use the full array
185 */
186 dc->scale_factor = (double) dc->reuse_index_array_size / (max_ratio - 1);
187
188 for (i = 0; i < dc->reuse_index_array_size; i++)
189 {
190 dc->reuse_index_array[i] = (int)
191 (((double) dc->half_life / dc->delta_reuse) *
192 log10 (1.0 / (dc->reuse * (1.0 + ((double) i / dc->scale_factor))))
193 / log10 (0.5));
194 }
195
196 dc->enabled = ON;
197}
198
199static double
200ospf6_damp_decay (time_t tdiff)
201{
202 int index = tdiff / dc->delta_t;
203
204 if (index >= dc->decay_array_size)
205 return 0;
206
207 return dc->decay_array[index];
208}
209
210static int
211ospf6_damp_reuse_index (int penalty)
212{
213 int index;
214
215 index = (int) (((double) penalty / dc->reuse - 1.0) * dc->scale_factor);
216
217 if (index >= dc->reuse_index_array_size)
218 index = dc->reuse_index_array_size - 1;
219
220 return (dc->reuse_index_array[index] - dc->reuse_index_array[0]);
221}
222
223static int
224ospf6_reuse_list_lookup (struct ospf6_damp_info *di)
225{
226 struct ospf6_damp_info *info;
227
228 for (info = dc->reuse_list_array[di->index]; info; info = info->next)
229 {
230 if (info == di)
231 return 1;
232 }
233 return 0;
234}
235
236static void
237ospf6_reuse_list_remove (struct ospf6_damp_info *di)
238{
239 if (di->prev)
240 di->prev->next = di->next;
241 else
242 dc->reuse_list_array[di->index] = di->next;
243 if (di->next)
244 di->next->prev = di->prev;
245
246 di->index = -1;
247 di->prev = NULL;
248 di->next = NULL;
249}
250
251static void
252ospf6_reuse_list_add (struct ospf6_damp_info *di)
253{
254 /* set the index of reuse-array */
255 di->index = (reuse_array_offset + (ospf6_damp_reuse_index (di->penalty)))
256 % dc->reuse_list_size;
257
258 /* insert to the head of the reuse list */
259 di->next = dc->reuse_list_array[di->index];
260 if (di->next)
261 di->next->prev = di;
262 di->prev = NULL;
263 dc->reuse_list_array[di->index] = di;
264}
265
266/* When we quit damping for a target, we should execute proper event
267 which have been postponed during damping */
268static void
269ospf6_damp_stop (struct ospf6_damp_info *di)
270{
271 time_t t_now;
272 char namebuf[64];
273 struct timeval now;
274
275 if (IS_OSPF6_DEBUG_DAMP)
276 {
277 t_now = time (NULL);
278 prefix2str (&di->name, namebuf, sizeof (namebuf));
279 gettimeofday (&now, NULL);
280 zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
281 now.tv_sec, now.tv_usec,
hassofa2b17e2004-03-04 17:45:00 +0000282 (long)t_now, di->type, namebuf);
paul718e3742002-12-13 20:15:29 +0000283 }
284
285 /* set flag indicates that we're damping this target */
286 di->damping = OFF;
287
288 /* if the target's current status differ from that it should be,
289 execute the proper event to repair his status */
290 if (di->target_status != di->event_type)
291 {
292 (*(di->event)) (di->target);
293 di->target_status = di->event_type;
294
295 di->event = NULL;
296 di->event_type = event_none;
297 }
298}
299
300/* ospf6_reuse_timer is called every DELTA_REUSE seconds.
301 Each route in the current reuse-list is evaluated
302 and is used or requeued */
303int
304ospf6_damp_reuse_timer (struct thread *t)
305{
306 struct ospf6_damp_info *di, *next;
307 time_t t_now, t_diff;
308 char namebuf[64];
309 struct timeval now;
310
311 /* Restart the reuse timer */
312 ospf6_reuse_thread =
313 thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
314
315 t_now = time (NULL);
316
317 /* get the damp info list head */
318 di = dc->reuse_list_array[reuse_array_offset];
319 dc->reuse_list_array[reuse_array_offset] = NULL;
320
321 /* rotate the circular reuse list head array */
322 reuse_array_offset = (reuse_array_offset + 1) % dc->reuse_list_size;
323
324 /* for each damp info */
325 while (di)
326 {
327 next = di->next;
328 di->next = NULL;
329
330 /* Update penalty */
331 t_diff = t_now - di->t_updated;
332 di->t_updated = t_now;
333 di->penalty = (int)
334 ((double) di->penalty * ospf6_damp_decay (t_diff));
335 /* configration of ceiling may be just changed */
336 if (di->penalty > dc->ceiling)
337 di->penalty = dc->ceiling;
338
339 if (IS_OSPF6_DEBUG_DAMP)
340 {
341 prefix2str (&di->name, namebuf, sizeof (namebuf));
342 gettimeofday (&now, NULL);
343 zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
344 now.tv_sec, now.tv_usec,
345 di->type, namebuf, di->penalty);
346 }
347
348 /* If the penalty becomes under reuse,
349 call real event that we have been postponed. */
350 if (di->penalty < dc->reuse && di->damping == ON)
351 ospf6_damp_stop (di);
352
353 /* If the penalty becomes less than the half of the
354 reuse value, this damp info will be freed from reuse-list,
355 by assuming that it is considered to be stable enough already,
356 and there's no need to maintain flapping history for this. */
357 if (di->penalty <= dc->reuse / 2)
358 {
359 ospf6_damp_delete (di->type, &di->name);
360 di = next;
361 continue;
362 }
363
364 /* re-insert to the reuse-list */
365 ospf6_reuse_list_add (di);
366
367 di = next;
368 }
369
370 return 0;
371}
372
373static void
374ospf6_damp_event (damp_event_t event_type,
375 u_short type, struct prefix *name,
376 int (*event) (void *), void *target)
377{
378 time_t t_now, t_diff;
379 struct ospf6_damp_info *di;
380 char namebuf[64];
381 struct timeval now;
382
383 if (dc->enabled == OFF)
384 {
385 (*event) (target);
386 return;
387 }
388
389 di = ospf6_damp_lookup (type, name);
390 if (! di)
391 di = ospf6_damp_create (type, name);
392
393 t_now = time (NULL);
394
395 di->event = event;
396 di->target = target;
397 di->event_type = event_type;
398
399 if (! ospf6_reuse_list_lookup (di))
400 di->t_start = t_now;
401 else
402 {
403 ospf6_reuse_list_remove (di);
404
405 t_diff = t_now - di->t_updated;
406 di->penalty = (int) (di->penalty * ospf6_damp_decay (t_diff));
407 }
408
409 /* penalty only on down event */
410 if (event_type == event_down)
411 {
412 di->flap++;
413 di->penalty += dc->default_penalty;
414 }
415
416 /* limit penalty up to ceiling */
417 if (di->penalty > dc->ceiling)
418 di->penalty = dc->ceiling;
419
420 if (IS_OSPF6_DEBUG_DAMP)
421 {
422 prefix2str (&di->name, namebuf, sizeof (namebuf));
423 gettimeofday (&now, NULL);
424 zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
425 now.tv_sec, now.tv_usec,
426 di->type, namebuf, di->penalty);
427 }
428
429 /* if penalty < reuse, stop damping here */
430 if (di->penalty < dc->reuse && di->damping == ON)
431 {
432 if (IS_OSPF6_DEBUG_DAMP)
433 {
434 prefix2str (&di->name, namebuf, sizeof (namebuf));
435 gettimeofday (&now, NULL);
436 zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
437 now.tv_sec, now.tv_usec,
hassofa2b17e2004-03-04 17:45:00 +0000438 (long)t_now, di->type, namebuf);
paul718e3742002-12-13 20:15:29 +0000439 }
440 di->damping = OFF;
441 }
442
443 /* if event == up and if penalty >= suppress , start damping here */
444 if (di->event_type == event_up && di->penalty >= dc->suppress &&
445 di->damping == OFF)
446 {
447 if (IS_OSPF6_DEBUG_DAMP)
448 {
449 prefix2str (&di->name, namebuf, sizeof (namebuf));
450 gettimeofday (&now, NULL);
451 zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
452 now.tv_sec, now.tv_usec,
hassofa2b17e2004-03-04 17:45:00 +0000453 (long)t_now, type, namebuf);
paul718e3742002-12-13 20:15:29 +0000454 }
455 di->damping = ON;
456 }
457
458 /* execute event if we're not damping */
459 if (di->damping == OFF)
460 {
461 (*(di->event)) (di->target);
462 di->target_status = di->event_type;
463 }
464
465 /* if the penalty goes beyond suppress value, start damping */
466 if (di->penalty >= dc->suppress && di->damping == OFF)
467 {
468 if (IS_OSPF6_DEBUG_DAMP)
469 {
470 prefix2str (name, namebuf, sizeof (namebuf));
471 gettimeofday (&now, NULL);
472 zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
473 now.tv_sec, now.tv_usec,
hassofa2b17e2004-03-04 17:45:00 +0000474 (long) t_now, type, namebuf);
paul718e3742002-12-13 20:15:29 +0000475 }
476 di->damping = ON;
477 }
478
479 /* update last-updated-time field */
480 di->t_updated = t_now;
481
482 /* Insert it into the reuse list */
483 ospf6_reuse_list_add (di);
484}
485
486void
487ospf6_damp_event_up (u_short type, struct prefix *name,
488 int (*event) (void *), void *target)
489{
490 struct timeval now;
491
492 gettimeofday (&now, NULL);
493 if (IS_OSPF6_DEBUG_DAMP)
494 zlog_info ("DAMP: Up Event at %lu.%06lu", now.tv_sec, now.tv_usec);
495
496 ospf6_damp_event (event_up, type, name, event, target);
497}
498
499void
500ospf6_damp_event_down (u_short type, struct prefix *name,
501 int (*event) (void *), void *target)
502{
503 struct timeval now;
504
505 gettimeofday (&now, NULL);
506 if (IS_OSPF6_DEBUG_DAMP)
507 zlog_info ("DAMP: Down Event at %lu.%06lu", now.tv_sec, now.tv_usec);
508
509 ospf6_damp_event (event_down, type, name, event, target);
510}
511
512int
513ospf6_damp_debug_thread (struct thread *thread)
514{
515 int i;
516 struct ospf6_damp_info *di;
517 char buf[256];
518 time_t t_now;
519 struct timeval now;
520
521 for (i = 0; i < dc->reuse_list_size; i++)
522 {
523 for (di = dc->reuse_list_array[i]; di; di = di->next)
524 {
525 t_now = time (NULL);
526 gettimeofday (&now, NULL);
527 prefix2str (&di->name, buf, sizeof (buf));
528 zlog_info ("DAMP: %lu.%06lu %c %-32s penalty %7u",
529 now.tv_sec, now.tv_usec,
530 (di->damping == ON ? 'D' : 'A'), buf,
531 (u_int) (di->penalty *
532 ospf6_damp_decay (t_now - di->t_updated)));
533 }
534 }
535 thread_add_timer (master, ospf6_damp_debug_thread, NULL, 1);
536 return 0;
537}
538
539DEFUN (show_ipv6_ospf6_route_flapping,
540 show_ipv6_ospf6_route_flapping_cmd,
541 "show ipv6 ospf6 route flapping",
542 SHOW_STR
543 IP6_STR
544 OSPF6_STR)
545{
546 int i;
547 struct ospf6_damp_info *di;
548 char buf[256];
549 time_t t_now;
550
551 t_now = time (NULL);
552 vty_out (vty, "%c %-32s %7s%s", ' ', "Prefix", "penalty", VTY_NEWLINE);
553
554 for (i = 0; i < dc->reuse_list_size; i++)
555 {
556 for (di = dc->reuse_list_array[i]; di; di = di->next)
557 {
558 prefix2str (&di->name, buf, sizeof (buf));
559 vty_out (vty, "%c %-32s %7u%s",
560 (di->damping == ON ? 'D' : ' '), buf,
561 (u_int) (di->penalty *
562 ospf6_damp_decay (t_now - di->t_updated)),
563 VTY_NEWLINE);
564 }
565 }
566
567 return CMD_SUCCESS;
568}
569
paula2c62832003-04-23 17:01:31 +0000570DEFUN (ospf6_flap_damping_route,
571 ospf6_flap_damping_route_cmd,
paul718e3742002-12-13 20:15:29 +0000572 "flap-damping route <0-4294967295> <0-4294967295> "
573 "<0-4294967295> <0-4294967295>",
574 "enable flap dampening\n"
575 "enable route flap dampening\n"
576 "half-life in second\n"
577 "reuse value\n"
578 "suppress value\n"
579 "t-hold in second (maximum time that the target can be damped)\n"
580 )
581{
582 u_int half_life, reuse, suppress, t_hold;
583
584 if (argc)
585 {
586 half_life = (u_int) strtoul (argv[0], NULL, 10);
587 reuse = (u_int) strtoul (argv[1], NULL, 10);
588 suppress = (u_int) strtoul (argv[2], NULL, 10);
589 t_hold = (u_int) strtoul (argv[3], NULL, 10);
590 }
591 else
592 {
593 half_life = (u_int) DEFAULT_HALF_LIFE;
594 reuse = (u_int) DEFAULT_REUSE;
595 suppress = (u_int) DEFAULT_SUPPRESS;
596 t_hold = (u_int) DEFAULT_HALF_LIFE * 4;
597 }
598
599 if (reuse && suppress && reuse >= suppress)
600 {
601 vty_out (vty, "reuse value exceeded suppress value, failed%s\n",
602 VTY_NEWLINE);
603 return CMD_SUCCESS;
604 }
605
606 if (half_life && t_hold && half_life >= t_hold)
607 {
608 vty_out (vty, "half-life exceeded t-hold, failed%s\n", VTY_NEWLINE);
609 return CMD_SUCCESS;
610 }
611
612 ospf6_damp_init_config (half_life, reuse, suppress, t_hold);
613
614 if (ospf6_reuse_thread == NULL)
615 ospf6_reuse_thread =
616 thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
617
618 return CMD_SUCCESS;
619}
620
621DEFUN (show_ipv6_ospf6_damp_config,
622 show_ipv6_ospf6_camp_config_cmd,
623 "show ipv6 ospf6 damp config",
624 SHOW_STR
625 IP6_STR
626 OSPF6_STR
627 "Flap-dampening information\n"
628 "shows dampening configuration\n"
629 )
630{
631 int i;
632
633 vty_out (vty, "%10s %10s %10s %10s%s",
634 "Half life", "Suppress", "Reuse", "T-hold",
635 VTY_NEWLINE);
636 vty_out (vty, "%10u %10u %10u %10u%s",
637 dc->half_life, dc->suppress, dc->reuse, dc->t_hold,
638 VTY_NEWLINE);
639 vty_out (vty, "%s", VTY_NEWLINE);
640
641 vty_out (vty, "Delta-t = %u%s", dc->delta_t, VTY_NEWLINE);
642 vty_out (vty, "Delta-Reuse = %u%s", dc->delta_reuse, VTY_NEWLINE);
643 vty_out (vty, "Default-Penalty = %u%s", dc->default_penalty, VTY_NEWLINE);
644 vty_out (vty, "Ceiling = %u%s", dc->ceiling, VTY_NEWLINE);
645 vty_out (vty, "ScaleFactor = %f%s", dc->scale_factor, VTY_NEWLINE);
646
647 vty_out (vty, "DecayArray(%d) =%s", dc->decay_array_size, VTY_NEWLINE);
648 for (i = 0; i < dc->decay_array_size; i++)
649 {
650 if (i % 10 == 0)
651 vty_out (vty, " ");
652 vty_out (vty, " %f", dc->decay_array[i]);
653 if (i % 10 == 0)
654 vty_out (vty, "%s", VTY_NEWLINE);
655 }
656 vty_out (vty, "%s", VTY_NEWLINE);
657
658 vty_out (vty, "ReuseIndexArray(%d) =%s",
659 dc->reuse_index_array_size, VTY_NEWLINE);
660 for (i = 0; i < dc->reuse_index_array_size; i++)
661 {
662 if (i % 10 == 0)
663 vty_out (vty, " ");
664 vty_out (vty, " %d", dc->reuse_index_array[i]);
665 if (i % 10 == 0)
666 vty_out (vty, "%s", VTY_NEWLINE);
667 }
668 vty_out (vty, "%s", VTY_NEWLINE);
669
670 return CMD_SUCCESS;
671}
672
673void
674ospf6_damp_config_write (struct vty *vty)
675{
676 if (dc->enabled == ON)
677 {
678 vty_out (vty, " flap-damping route %u %u %u %u%s",
679 dc->half_life, dc->reuse, dc->suppress, dc->t_hold,
680 VTY_NEWLINE);
681 }
682}
683
684DEFUN (debug_ospf6_damp,
685 debug_ospf6_damp_cmd,
686 "debug ospf6 damp",
687 DEBUG_STR
688 OSPF6_STR
689 "Flap-dampening information\n"
690 )
691{
692 ospf6_damp_debug = 1;
693 return CMD_SUCCESS;
694}
695
696DEFUN (no_debug_ospf6_damp,
697 no_debug_ospf6_damp_cmd,
698 "no debug ospf6 damp",
699 NO_STR
700 DEBUG_STR
701 OSPF6_STR
702 "Flap-dampening information\n"
703 )
704{
705 ospf6_damp_debug = 0;
706 return CMD_SUCCESS;
707}
708
709DEFUN (show_debug_ospf6_damp,
710 show_debug_ospf6_damp_cmd,
711 "show debugging ospf6 damp",
712 SHOW_STR
713 DEBUG_STR
714 OSPF6_STR
715 "Flap-dampening information\n"
716 )
717{
718 vty_out (vty, "debugging ospf6 damp is ");
719 if (IS_OSPF6_DEBUG_DAMP)
720 vty_out (vty, "enabled.");
721 else
722 vty_out (vty, "disabled.");
723 vty_out (vty, "%s", VTY_NEWLINE);
724 return CMD_SUCCESS;
725}
726
727void
728ospf6_damp_init ()
729{
730 int i;
731 for (i = 0; i < OSPF6_DAMP_TYPE_MAX; i++)
732 damp_info_table[i] = route_table_init ();
733
734 install_element (VIEW_NODE, &show_ipv6_ospf6_route_flapping_cmd);
735 install_element (ENABLE_NODE, &show_ipv6_ospf6_route_flapping_cmd);
736 install_element (ENABLE_NODE, &show_ipv6_ospf6_camp_config_cmd);
paula2c62832003-04-23 17:01:31 +0000737 install_element (OSPF6_NODE, &ospf6_flap_damping_route_cmd);
paul718e3742002-12-13 20:15:29 +0000738
739 install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd);
740 install_element (CONFIG_NODE, &debug_ospf6_damp_cmd);
741 install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd);
742
743 thread_add_event (master, ospf6_damp_debug_thread, NULL, 0);
744}
745
746#endif /* HAVE_OSPF6_DAMP */
747
748