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

« back to all changes in this revision

Viewing changes to bgpd/bgp_damp.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
/* BGP flap dampening
 
2
   Copyright (C) 2001 IP Infusion Inc.
 
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 Free
 
18
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
02111-1307, USA.  */
 
20
 
 
21
#include <zebra.h>
 
22
#include <math.h>
 
23
 
 
24
#include "prefix.h"
 
25
#include "memory.h"
 
26
#include "command.h"
 
27
#include "log.h"
 
28
#include "thread.h"
 
29
 
 
30
#include "bgpd/bgpd.h"
 
31
#include "bgpd/bgp_damp.h"
 
32
#include "bgpd/bgp_table.h"
 
33
#include "bgpd/bgp_route.h"
 
34
#include "bgpd/bgp_attr.h" 
 
35
#include "bgpd/bgp_advertise.h"
 
36
 
 
37
/* Global variable to access damping configuration */
 
38
struct bgp_damp_config bgp_damp_cfg;
 
39
struct bgp_damp_config *damp = &bgp_damp_cfg;
 
40
 
 
41
/* Utility macro to add and delete BGP dampening information to no
 
42
   used list.  */
 
43
#define BGP_DAMP_LIST_ADD(N,A)  BGP_INFO_ADD(N,A,no_reuse_list)
 
44
#define BGP_DAMP_LIST_DEL(N,A)  BGP_INFO_DEL(N,A,no_reuse_list)
 
45
 
 
46
/* Calculate reuse list index by penalty value.  */
 
47
static int
 
48
bgp_reuse_index (int penalty)
 
49
{
 
50
  unsigned int i;
 
51
  int index;
 
52
 
 
53
  i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
 
54
  
 
55
  if ( i >= damp->reuse_index_size )
 
56
    i = damp->reuse_index_size - 1;
 
57
 
 
58
  index = damp->reuse_index[i] - damp->reuse_index[0];
 
59
 
 
60
  return (damp->reuse_offset + index) % damp->reuse_list_size;  
 
61
}
 
62
 
 
63
/* Add BGP dampening information to reuse list.  */
 
64
static void 
 
65
bgp_reuse_list_add (struct bgp_damp_info *bdi)
 
66
{
 
67
  int index;
 
68
 
 
69
  index = bdi->index = bgp_reuse_index (bdi->penalty);
 
70
 
 
71
  bdi->prev = NULL;
 
72
  bdi->next = damp->reuse_list[index];
 
73
  if (damp->reuse_list[index])
 
74
    damp->reuse_list[index]->prev = bdi;
 
75
  damp->reuse_list[index] = bdi;
 
76
}
 
77
 
 
78
/* Delete BGP dampening information from reuse list.  */
 
79
static void
 
80
bgp_reuse_list_delete (struct bgp_damp_info *bdi)
 
81
{
 
82
  if (bdi->next)
 
83
    bdi->next->prev = bdi->prev;
 
84
  if (bdi->prev)
 
85
    bdi->prev->next = bdi->next;
 
86
  else
 
87
    damp->reuse_list[bdi->index] = bdi->next;
 
88
}   
 
89
 
 
90
/* Return decayed penalty value.  */
 
91
int 
 
92
bgp_damp_decay (time_t tdiff, int penalty)
 
93
{
 
94
  unsigned int i;
 
95
 
 
96
  i = (int) ((double) tdiff / DELTA_T);
 
97
 
 
98
  if (i == 0)
 
99
    return penalty; 
 
100
  
 
101
  if (i >= damp->decay_array_size)
 
102
    return 0;
 
103
 
 
104
  return (int) (penalty * damp->decay_array[i]);
 
105
}
 
106
 
 
107
/* Handler of reuse timer event.  Each route in the current reuse-list
 
108
   is evaluated.  RFC2439 Section 4.8.7.  */
 
109
int
 
110
bgp_reuse_timer (struct thread *t)
 
111
{
 
112
  struct bgp_damp_info *bdi;
 
113
  struct bgp_damp_info *next;
 
114
  time_t t_now, t_diff;
 
115
  struct bgp *bgp;
 
116
  int bgp_process (struct bgp *, struct bgp_node *, afi_t, safi_t);
 
117
 
 
118
  damp->t_reuse = NULL;
 
119
  damp->t_reuse =
 
120
    thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
 
121
 
 
122
  bgp = bgp_get_default ();
 
123
  if (! bgp)
 
124
    return 0;
 
125
 
 
126
  t_now = time (NULL);
 
127
 
 
128
  /* 1.  save a pointer to the current zeroth queue head and zero the
 
129
     list head entry.  */
 
130
  bdi = damp->reuse_list[damp->reuse_offset];
 
131
  damp->reuse_list[damp->reuse_offset] = NULL;
 
132
 
 
133
  /* 2.  set offset = modulo reuse-list-size ( offset + 1 ), thereby
 
134
     rotating the circular queue of list-heads.  */
 
135
  damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
 
136
 
 
137
  /* 3. if ( the saved list head pointer is non-empty ) */
 
138
  for (; bdi; bdi = next)
 
139
    {
 
140
      next = bdi->next;
 
141
 
 
142
      /* Set t-diff = t-now - t-updated.  */
 
143
      t_diff = t_now - bdi->t_updated;
 
144
 
 
145
      /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
 
146
      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);   
 
147
 
 
148
      /* Set t-updated = t-now.  */
 
149
      bdi->t_updated = t_now;
 
150
 
 
151
      /* if (figure-of-merit < reuse).  */
 
152
      if (bdi->penalty < damp->reuse_limit)
 
153
        {
 
154
          /* Reuse the route.  */
 
155
          UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
 
156
          bdi->suppress_time = 0;
 
157
 
 
158
          if (bdi->lastrecord == BGP_RECORD_UPDATE)
 
159
            {
 
160
              UNSET_FLAG (bdi->binfo->flags, BGP_INFO_HISTORY);
 
161
              bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
 
162
                                       bdi->afi, bdi->safi);   
 
163
              bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
 
164
            }
 
165
 
 
166
          if (bdi->penalty <= damp->reuse_limit / 2.0)
 
167
            bgp_damp_info_free (bdi, 1);
 
168
          else
 
169
            BGP_DAMP_LIST_ADD (damp, bdi);
 
170
        }
 
171
      else
 
172
        /* Re-insert into another list (See RFC2439 Section 4.8.6).  */
 
173
        bgp_reuse_list_add (bdi);
 
174
    }
 
175
 
 
176
  return 0;
 
177
}
 
178
 
 
179
/* A route becomes unreachable (RFC2439 Section 4.8.2).  */
 
180
int
 
181
bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
 
182
                   afi_t afi, safi_t safi, int attr_change)
 
183
{
 
184
  time_t t_now;
 
185
  struct bgp_damp_info *bdi;
 
186
  double last_penalty = 0;
 
187
  
 
188
  t_now = time (NULL);
 
189
 
 
190
  /* Processing Unreachable Messages.  */
 
191
  bdi = binfo->damp_info;
 
192
 
 
193
  if (bdi == NULL)
 
194
    {
 
195
      /* If there is no previous stability history. */
 
196
 
 
197
      /* RFC2439 said:
 
198
         1. allocate a damping structure.
 
199
         2. set figure-of-merit = 1.
 
200
         3. withdraw the route.  */
 
201
 
 
202
      bdi =  XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
 
203
      bdi->binfo = binfo;
 
204
      bdi->rn = rn;
 
205
      bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
 
206
      bdi->flap = 1;
 
207
      bdi->start_time = t_now;
 
208
      bdi->suppress_time = 0;
 
209
      bdi->index = -1;
 
210
      bdi->afi = afi;
 
211
      bdi->safi = safi;
 
212
      binfo->damp_info = bdi;
 
213
      BGP_DAMP_LIST_ADD (damp, bdi);
 
214
    }
 
215
  else
 
216
    {
 
217
      last_penalty = bdi->penalty;
 
218
 
 
219
      /* 1. Set t-diff = t-now - t-updated.  */
 
220
      bdi->penalty = 
 
221
        (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty) 
 
222
         + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
 
223
 
 
224
      if (bdi->penalty > damp->ceiling)
 
225
        bdi->penalty = damp->ceiling;
 
226
 
 
227
      bdi->flap++;
 
228
    }
 
229
  
 
230
  bdi->lastrecord = BGP_RECORD_WITHDRAW;
 
231
  bdi->t_updated = t_now;
 
232
 
 
233
  /* Make this route as historical status.  */
 
234
  SET_FLAG (binfo->flags, BGP_INFO_HISTORY);
 
235
 
 
236
  /* Remove the route from a reuse list if it is on one.  */
 
237
  if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
 
238
    {
 
239
      /* If decay rate isn't equal to 0, reinsert brn. */  
 
240
      if (bdi->penalty != last_penalty)
 
241
        {
 
242
          bgp_reuse_list_delete (bdi);
 
243
          bgp_reuse_list_add (bdi);  
 
244
        }
 
245
      return BGP_DAMP_SUPPRESSED; 
 
246
    }
 
247
 
 
248
  /* If not suppressed before, do annonunce this withdraw and
 
249
     insert into reuse_list.  */
 
250
  if (bdi->penalty >= damp->suppress_value)
 
251
    {
 
252
      SET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
 
253
      bdi->suppress_time = t_now;
 
254
      BGP_DAMP_LIST_DEL (damp, bdi);
 
255
      bgp_reuse_list_add (bdi);
 
256
    }
 
257
 
 
258
  return BGP_DAMP_USED;
 
259
}
 
260
 
 
261
int
 
262
bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn, 
 
263
                 afi_t afi, safi_t safi)
 
264
{
 
265
  time_t t_now;
 
266
  struct bgp_damp_info *bdi;
 
267
  int status;
 
268
 
 
269
  bdi = binfo->damp_info;
 
270
  if (! bdi)
 
271
    return BGP_DAMP_USED;
 
272
 
 
273
  t_now = time (NULL);
 
274
  UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY); 
 
275
 
 
276
  bdi->lastrecord = BGP_RECORD_UPDATE;
 
277
  bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
 
278
 
 
279
  if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
 
280
      && (bdi->penalty < damp->suppress_value))
 
281
    status = BGP_DAMP_USED;
 
282
  else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
 
283
           && (bdi->penalty < damp->reuse_limit) )
 
284
    {
 
285
      UNSET_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED);
 
286
      bgp_reuse_list_delete (bdi);
 
287
      BGP_DAMP_LIST_ADD (damp, bdi);
 
288
      bdi->suppress_time = 0;
 
289
      status = BGP_DAMP_USED;
 
290
    }
 
291
  else
 
292
    status = BGP_DAMP_SUPPRESSED;  
 
293
 
 
294
  if (bdi->penalty > damp->reuse_limit / 2.0)
 
295
    bdi->t_updated = t_now;
 
296
  else
 
297
    bgp_damp_info_free (bdi, 0);
 
298
        
 
299
  return status;
 
300
}
 
301
 
 
302
/* Remove dampening information and history route.  */
 
303
int 
 
304
bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
 
305
{
 
306
  time_t t_now, t_diff;
 
307
  struct bgp_damp_info *bdi;
 
308
 
 
309
  t_now = time (NULL);
 
310
  bdi = binfo->damp_info;
 
311
 
 
312
  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
 
313
    {
 
314
      t_diff = t_now - bdi->suppress_time;
 
315
 
 
316
      if (t_diff >= damp->max_suppress_time)
 
317
        {
 
318
          UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
 
319
          bgp_reuse_list_delete (bdi);
 
320
          BGP_DAMP_LIST_ADD (damp, bdi);
 
321
          bdi->penalty = damp->reuse_limit;
 
322
          bdi->suppress_time = 0;
 
323
          bdi->t_updated = t_now;
 
324
          
 
325
          /* Need to announce UPDATE once this binfo is usable again. */
 
326
          if (bdi->lastrecord == BGP_RECORD_UPDATE)
 
327
            return 1;
 
328
          else
 
329
            return 0;
 
330
        }
 
331
    }
 
332
  else
 
333
    {
 
334
      t_diff = t_now - bdi->t_updated;
 
335
      bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
 
336
 
 
337
      if (bdi->penalty <= damp->reuse_limit / 2.0)
 
338
        {
 
339
          /* release the bdi, bdi->binfo. */  
 
340
          bgp_damp_info_free (bdi, 1);
 
341
          return 0;
 
342
        }            
 
343
      else
 
344
        bdi->t_updated = t_now;
 
345
    }       
 
346
  return 0;
 
347
}
 
348
 
 
349
void
 
350
bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
 
351
{
 
352
  struct bgp_info *binfo;
 
353
  void bgp_info_delete (struct bgp_node *, struct bgp_info *);
 
354
  void bgp_info_free (struct bgp_info *);
 
355
 
 
356
  if (! bdi)
 
357
    return;
 
358
 
 
359
  binfo = bdi->binfo;
 
360
  binfo->damp_info = NULL;
 
361
 
 
362
  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
 
363
    bgp_reuse_list_delete (bdi);
 
364
  else
 
365
    BGP_DAMP_LIST_DEL (damp, bdi);
 
366
 
 
367
  UNSET_FLAG (binfo->flags, BGP_INFO_DAMPED);
 
368
  UNSET_FLAG (binfo->flags, BGP_INFO_HISTORY);
 
369
 
 
370
  if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
 
371
    {
 
372
      bgp_info_delete (bdi->rn, binfo);
 
373
      bgp_info_free (binfo);
 
374
      bgp_unlock_node (bdi->rn);
 
375
    }
 
376
  XFREE (MTYPE_BGP_DAMP_INFO, bdi);
 
377
}
 
378
 
 
379
void
 
380
bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
 
381
{
 
382
  double reuse_max_ratio;
 
383
  unsigned int i;
 
384
  double j;
 
385
        
 
386
  damp->suppress_value = sup;
 
387
  damp->half_life = hlife;
 
388
  damp->reuse_limit = reuse;
 
389
  damp->max_suppress_time = maxsup;
 
390
 
 
391
  /* Initialize params per bgp_damp_config. */
 
392
  damp->reuse_index_size = REUSE_ARRAY_SIZE;
 
393
 
 
394
  damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life))); 
 
395
 
 
396
  /* Decay-array computations */
 
397
  damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
 
398
  damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
 
399
                               sizeof(double) * (damp->decay_array_size));
 
400
  damp->decay_array[0] = 1.0;
 
401
  damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
 
402
 
 
403
  /* Calculate decay values for all possible times */
 
404
  for (i = 2; i < damp->decay_array_size; i++)
 
405
    damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
 
406
        
 
407
  /* Reuse-list computations */
 
408
  i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
 
409
  if (i > REUSE_LIST_SIZE || i == 0)
 
410
    i = REUSE_LIST_SIZE;
 
411
  damp->reuse_list_size = i; 
 
412
 
 
413
  damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY, 
 
414
                              damp->reuse_list_size 
 
415
                              * sizeof (struct bgp_reuse_node *));
 
416
  memset (damp->reuse_list, 0x00, 
 
417
          damp->reuse_list_size * sizeof (struct bgp_reuse_node *));  
 
418
 
 
419
  /* Reuse-array computations */
 
420
  damp->reuse_index = XMALLOC (MTYPE_BGP_DAMP_ARRAY, 
 
421
                               sizeof(int) * damp->reuse_index_size);
 
422
  memset (damp->reuse_index, 0x00,
 
423
          damp->reuse_list_size * sizeof (int));
 
424
 
 
425
  reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
 
426
  j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
 
427
  if ( reuse_max_ratio > j && j != 0 )
 
428
    reuse_max_ratio = j;
 
429
 
 
430
  damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
 
431
 
 
432
  for (i = 0; i < damp->reuse_index_size; i++)
 
433
    {
 
434
      damp->reuse_index[i] = 
 
435
        (int)(((double)damp->half_life / DELTA_REUSE)
 
436
              * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
 
437
    }
 
438
}
 
439
 
 
440
int
 
441
bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
 
442
                 unsigned int reuse, unsigned int suppress, time_t max)
 
443
{
 
444
  if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
 
445
    {
 
446
      if (damp->half_life == half
 
447
          && damp->reuse_limit == reuse
 
448
          && damp->suppress_value == suppress
 
449
          && damp->max_suppress_time == max)
 
450
        return 0;
 
451
      bgp_damp_disable (bgp, afi, safi);
 
452
    }
 
453
 
 
454
  SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
 
455
  bgp_damp_parameter_set (half, reuse, suppress, max);
 
456
 
 
457
  /* Register reuse timer.  */
 
458
  if (! damp->t_reuse)
 
459
    damp->t_reuse = 
 
460
      thread_add_timer (master, bgp_reuse_timer, NULL, DELTA_REUSE);
 
461
 
 
462
  return 0;
 
463
}
 
464
 
 
465
void
 
466
bgp_damp_config_clean (struct bgp_damp_config *damp)
 
467
{
 
468
  /* Free decay array */
 
469
  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
 
470
 
 
471
  /* Free reuse index array */
 
472
  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
 
473
 
 
474
  /* Free reuse list array. */
 
475
  XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
 
476
}
 
477
 
 
478
/* Clean all the bgp_damp_info stored in reuse_list. */
 
479
void
 
480
bgp_damp_info_clean ()
 
481
{
 
482
  unsigned int i;
 
483
  struct bgp_damp_info *bdi, *next;
 
484
 
 
485
  damp->reuse_offset = 0;
 
486
 
 
487
  for (i = 0; i < damp->reuse_list_size; i++)
 
488
    {
 
489
      if (! damp->reuse_list[i])
 
490
        continue;
 
491
 
 
492
      for (bdi = damp->reuse_list[i]; bdi; bdi = next)
 
493
        {
 
494
          next = bdi->next;
 
495
          bgp_damp_info_free (bdi, 1);
 
496
        }
 
497
      damp->reuse_list[i] = NULL;
 
498
    }
 
499
 
 
500
  for (bdi = damp->no_reuse_list; bdi; bdi = next)
 
501
    {
 
502
      next = bdi->next;
 
503
      bgp_damp_info_free (bdi, 1);
 
504
    }
 
505
  damp->no_reuse_list = NULL;
 
506
}
 
507
 
 
508
int
 
509
bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
 
510
{
 
511
  /* Cancel reuse thread. */
 
512
  if (damp->t_reuse )
 
513
    thread_cancel (damp->t_reuse);
 
514
  damp->t_reuse = NULL;
 
515
 
 
516
  /* Clean BGP dampening information.  */
 
517
  bgp_damp_info_clean ();
 
518
 
 
519
  /* Clear configuration */
 
520
  bgp_damp_config_clean (&bgp_damp_cfg);
 
521
 
 
522
  UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
 
523
  return 0;
 
524
}
 
525
 
 
526
int
 
527
bgp_config_write_damp (struct vty *vty)
 
528
{
 
529
  if (&bgp_damp_cfg)
 
530
    {
 
531
      if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
 
532
          && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
 
533
          && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
 
534
          && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
 
535
        vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
 
536
      else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
 
537
               && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
 
538
               && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
 
539
               && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
 
540
        vty_out (vty, " bgp dampening %ld%s",
 
541
                 bgp_damp_cfg.half_life/60,
 
542
                 VTY_NEWLINE);
 
543
      else
 
544
        vty_out (vty, " bgp dampening %ld %d %d %ld%s",
 
545
                 bgp_damp_cfg.half_life/60,
 
546
                 bgp_damp_cfg.reuse_limit,
 
547
                 bgp_damp_cfg.suppress_value,
 
548
                 bgp_damp_cfg.max_suppress_time/60,
 
549
                 VTY_NEWLINE);
 
550
      return 1;
 
551
    }
 
552
  return 0;
 
553
}
 
554
 
 
555
#define BGP_UPTIME_LEN 25
 
556
 
 
557
char *
 
558
bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len)
 
559
{
 
560
  time_t reuse_time = 0;
 
561
  struct tm *tm = NULL;
 
562
 
 
563
  if (penalty > damp->reuse_limit)
 
564
    {
 
565
      reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1])))); 
 
566
 
 
567
      if (reuse_time > damp->max_suppress_time)
 
568
        reuse_time = damp->max_suppress_time;
 
569
 
 
570
      tm = gmtime (&reuse_time);
 
571
    }
 
572
  else 
 
573
    reuse_time = 0;
 
574
 
 
575
  /* Making formatted timer strings. */
 
576
#define ONE_DAY_SECOND 60*60*24
 
577
#define ONE_WEEK_SECOND 60*60*24*7
 
578
  if (reuse_time == 0)
 
579
    snprintf (buf, len, "00:00:00");
 
580
  else if (reuse_time < ONE_DAY_SECOND)
 
581
    snprintf (buf, len, "%02d:%02d:%02d", 
 
582
              tm->tm_hour, tm->tm_min, tm->tm_sec);
 
583
  else if (reuse_time < ONE_WEEK_SECOND)
 
584
    snprintf (buf, len, "%dd%02dh%02dm", 
 
585
              tm->tm_yday, tm->tm_hour, tm->tm_min);
 
586
  else
 
587
    snprintf (buf, len, "%02dw%dd%02dh", 
 
588
              tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); 
 
589
 
 
590
  return buf;
 
591
}
 
592
 
 
593
void
 
594
bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)  
 
595
{
 
596
  struct bgp_damp_info *bdi;
 
597
  time_t t_now, t_diff;
 
598
  char timebuf[BGP_UPTIME_LEN];
 
599
  int penalty;
 
600
 
 
601
  /* BGP dampening information.  */
 
602
  bdi = binfo->damp_info;
 
603
 
 
604
  /* If dampening is not enabled or there is no dampening information,
 
605
     return immediately.  */
 
606
  if (! damp || ! bdi)
 
607
    return;
 
608
 
 
609
  /* Calculate new penalty.  */
 
610
  t_now = time (NULL);
 
611
  t_diff = t_now - bdi->t_updated;
 
612
  penalty = bgp_damp_decay (t_diff, bdi->penalty);
 
613
 
 
614
  vty_out (vty, "      Dampinfo: penalty %d, flapped %d times in %s",
 
615
           penalty, bdi->flap,
 
616
           peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
 
617
 
 
618
  if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
 
619
      && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
 
620
    vty_out (vty, ", reuse in %s",
 
621
             bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
 
622
 
 
623
  vty_out (vty, "%s", VTY_NEWLINE);
 
624
}
 
625
 
 
626
char *
 
627
bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo)
 
628
{
 
629
  struct bgp_damp_info *bdi;
 
630
  time_t t_now, t_diff;
 
631
  char timebuf[BGP_UPTIME_LEN];
 
632
  int penalty;
 
633
 
 
634
  /* BGP dampening information.  */
 
635
  bdi = binfo->damp_info;
 
636
 
 
637
  /* If dampening is not enabled or there is no dampening information,
 
638
     return immediately.  */
 
639
  if (! damp || ! bdi)
 
640
    return NULL;
 
641
 
 
642
  /* Calculate new penalty.  */
 
643
  t_now = time (NULL);
 
644
  t_diff = t_now - bdi->t_updated;
 
645
  penalty = bgp_damp_decay (t_diff, bdi->penalty);
 
646
 
 
647
  return  bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN);
 
648
}