blob: ac647239e47a576cafb312928a8fddeb117f37e9 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP flap dampening
2 Copyright (C) 2001 IP Infusion Inc.
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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"
Donald Sharp04907292016-01-07 10:03:01 -050029#include "filter.h"
paul718e3742002-12-13 20:15:29 +000030
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_damp.h"
33#include "bgpd/bgp_table.h"
34#include "bgpd/bgp_route.h"
35#include "bgpd/bgp_attr.h"
36#include "bgpd/bgp_advertise.h"
37
38/* Global variable to access damping configuration */
39struct bgp_damp_config bgp_damp_cfg;
Stephen Hemmingere9dc9f22009-05-15 10:19:31 -070040static struct bgp_damp_config *damp = &bgp_damp_cfg;
paul718e3742002-12-13 20:15:29 +000041
42/* Utility macro to add and delete BGP dampening information to no
43 used list. */
44#define BGP_DAMP_LIST_ADD(N,A) BGP_INFO_ADD(N,A,no_reuse_list)
45#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list)
David Lamparter6b0655a2014-06-04 06:53:35 +020046
paul718e3742002-12-13 20:15:29 +000047/* Calculate reuse list index by penalty value. */
48static int
49bgp_reuse_index (int penalty)
50{
paulfd79ac92004-10-13 05:06:08 +000051 unsigned int i;
paul718e3742002-12-13 20:15:29 +000052 int index;
53
54 i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
55
56 if ( i >= damp->reuse_index_size )
57 i = damp->reuse_index_size - 1;
58
59 index = damp->reuse_index[i] - damp->reuse_index[0];
60
61 return (damp->reuse_offset + index) % damp->reuse_list_size;
62}
63
64/* Add BGP dampening information to reuse list. */
65static void
66bgp_reuse_list_add (struct bgp_damp_info *bdi)
67{
68 int index;
69
70 index = bdi->index = bgp_reuse_index (bdi->penalty);
71
72 bdi->prev = NULL;
73 bdi->next = damp->reuse_list[index];
74 if (damp->reuse_list[index])
75 damp->reuse_list[index]->prev = bdi;
76 damp->reuse_list[index] = bdi;
77}
78
79/* Delete BGP dampening information from reuse list. */
80static void
81bgp_reuse_list_delete (struct bgp_damp_info *bdi)
82{
83 if (bdi->next)
84 bdi->next->prev = bdi->prev;
85 if (bdi->prev)
86 bdi->prev->next = bdi->next;
87 else
88 damp->reuse_list[bdi->index] = bdi->next;
89}
David Lamparter6b0655a2014-06-04 06:53:35 +020090
paul718e3742002-12-13 20:15:29 +000091/* Return decayed penalty value. */
92int
93bgp_damp_decay (time_t tdiff, int penalty)
94{
paulfd79ac92004-10-13 05:06:08 +000095 unsigned int i;
paul718e3742002-12-13 20:15:29 +000096
97 i = (int) ((double) tdiff / DELTA_T);
98
99 if (i == 0)
100 return penalty;
101
102 if (i >= damp->decay_array_size)
103 return 0;
104
105 return (int) (penalty * damp->decay_array[i]);
106}
107
108/* Handler of reuse timer event. Each route in the current reuse-list
109 is evaluated. RFC2439 Section 4.8.7. */
paul94f2b392005-06-28 12:44:16 +0000110static int
paul718e3742002-12-13 20:15:29 +0000111bgp_reuse_timer (struct thread *t)
112{
113 struct bgp_damp_info *bdi;
114 struct bgp_damp_info *next;
115 time_t t_now, t_diff;
paul41200852005-11-03 12:52:18 +0000116
paul718e3742002-12-13 20:15:29 +0000117 damp->t_reuse = NULL;
118 damp->t_reuse =
Donald Sharp774914f2015-10-14 08:50:39 -0400119 thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
paul718e3742002-12-13 20:15:29 +0000120
Stephen Hemminger65957882010-01-15 16:22:10 +0300121 t_now = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000122
123 /* 1. save a pointer to the current zeroth queue head and zero the
124 list head entry. */
125 bdi = damp->reuse_list[damp->reuse_offset];
126 damp->reuse_list[damp->reuse_offset] = NULL;
127
128 /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
129 rotating the circular queue of list-heads. */
130 damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
131
132 /* 3. if ( the saved list head pointer is non-empty ) */
133 for (; bdi; bdi = next)
134 {
paul41200852005-11-03 12:52:18 +0000135 struct bgp *bgp = bdi->binfo->peer->bgp;
136
paul718e3742002-12-13 20:15:29 +0000137 next = bdi->next;
138
139 /* Set t-diff = t-now - t-updated. */
140 t_diff = t_now - bdi->t_updated;
141
142 /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
143 bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
144
145 /* Set t-updated = t-now. */
146 bdi->t_updated = t_now;
147
148 /* if (figure-of-merit < reuse). */
149 if (bdi->penalty < damp->reuse_limit)
150 {
151 /* Reuse the route. */
Paul Jakma1a392d42006-09-07 00:24:49 +0000152 bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
paul718e3742002-12-13 20:15:29 +0000153 bdi->suppress_time = 0;
154
155 if (bdi->lastrecord == BGP_RECORD_UPDATE)
156 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000157 bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
paul718e3742002-12-13 20:15:29 +0000158 bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
159 bdi->afi, bdi->safi);
160 bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
161 }
162
163 if (bdi->penalty <= damp->reuse_limit / 2.0)
164 bgp_damp_info_free (bdi, 1);
165 else
166 BGP_DAMP_LIST_ADD (damp, bdi);
167 }
168 else
169 /* Re-insert into another list (See RFC2439 Section 4.8.6). */
170 bgp_reuse_list_add (bdi);
171 }
172
173 return 0;
174}
175
176/* A route becomes unreachable (RFC2439 Section 4.8.2). */
177int
178bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
179 afi_t afi, safi_t safi, int attr_change)
180{
181 time_t t_now;
Paul Jakmafb982c22007-05-04 20:15:47 +0000182 struct bgp_damp_info *bdi = NULL;
paul718e3742002-12-13 20:15:29 +0000183 double last_penalty = 0;
184
Stephen Hemminger65957882010-01-15 16:22:10 +0300185 t_now = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000186
187 /* Processing Unreachable Messages. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000188 if (binfo->extra)
189 bdi = binfo->extra->damp_info;
190
paul718e3742002-12-13 20:15:29 +0000191 if (bdi == NULL)
192 {
193 /* If there is no previous stability history. */
194
195 /* RFC2439 said:
196 1. allocate a damping structure.
197 2. set figure-of-merit = 1.
198 3. withdraw the route. */
199
200 bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
201 bdi->binfo = binfo;
202 bdi->rn = rn;
203 bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
204 bdi->flap = 1;
205 bdi->start_time = t_now;
206 bdi->suppress_time = 0;
207 bdi->index = -1;
208 bdi->afi = afi;
209 bdi->safi = safi;
Paul Jakmafb982c22007-05-04 20:15:47 +0000210 (bgp_info_extra_get (binfo))->damp_info = bdi;
paul718e3742002-12-13 20:15:29 +0000211 BGP_DAMP_LIST_ADD (damp, bdi);
212 }
213 else
214 {
215 last_penalty = bdi->penalty;
216
217 /* 1. Set t-diff = t-now - t-updated. */
218 bdi->penalty =
219 (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty)
220 + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
221
222 if (bdi->penalty > damp->ceiling)
223 bdi->penalty = damp->ceiling;
224
225 bdi->flap++;
226 }
227
Paul Jakma1a392d42006-09-07 00:24:49 +0000228 assert ((rn == bdi->rn) && (binfo == bdi->binfo));
229
paul718e3742002-12-13 20:15:29 +0000230 bdi->lastrecord = BGP_RECORD_WITHDRAW;
231 bdi->t_updated = t_now;
232
233 /* Make this route as historical status. */
Paul Jakma1a392d42006-09-07 00:24:49 +0000234 bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);
paul718e3742002-12-13 20:15:29 +0000235
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 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000252 bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
paul718e3742002-12-13 20:15:29 +0000253 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
261int
262bgp_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
Paul Jakmafb982c22007-05-04 20:15:47 +0000269 if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
paul718e3742002-12-13 20:15:29 +0000270 return BGP_DAMP_USED;
271
Stephen Hemminger65957882010-01-15 16:22:10 +0300272 t_now = bgp_clock ();
Paul Jakma1a392d42006-09-07 00:24:49 +0000273 bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
paul718e3742002-12-13 20:15:29 +0000274
275 bdi->lastrecord = BGP_RECORD_UPDATE;
276 bdi->penalty = bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty);
277
278 if (! CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
279 && (bdi->penalty < damp->suppress_value))
280 status = BGP_DAMP_USED;
281 else if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED)
282 && (bdi->penalty < damp->reuse_limit) )
283 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000284 bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
paul718e3742002-12-13 20:15:29 +0000285 bgp_reuse_list_delete (bdi);
286 BGP_DAMP_LIST_ADD (damp, bdi);
287 bdi->suppress_time = 0;
288 status = BGP_DAMP_USED;
289 }
290 else
291 status = BGP_DAMP_SUPPRESSED;
292
293 if (bdi->penalty > damp->reuse_limit / 2.0)
294 bdi->t_updated = t_now;
295 else
296 bgp_damp_info_free (bdi, 0);
297
298 return status;
299}
300
301/* Remove dampening information and history route. */
302int
303bgp_damp_scan (struct bgp_info *binfo, afi_t afi, safi_t safi)
304{
305 time_t t_now, t_diff;
306 struct bgp_damp_info *bdi;
Paul Jakmafb982c22007-05-04 20:15:47 +0000307
308 assert (binfo->extra && binfo->extra->damp_info);
309
Stephen Hemminger65957882010-01-15 16:22:10 +0300310 t_now = bgp_clock ();
Paul Jakmafb982c22007-05-04 20:15:47 +0000311 bdi = binfo->extra->damp_info;
paul718e3742002-12-13 20:15:29 +0000312
313 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
314 {
315 t_diff = t_now - bdi->suppress_time;
316
317 if (t_diff >= damp->max_suppress_time)
318 {
Paul Jakma1a392d42006-09-07 00:24:49 +0000319 bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
paul718e3742002-12-13 20:15:29 +0000320 bgp_reuse_list_delete (bdi);
321 BGP_DAMP_LIST_ADD (damp, bdi);
322 bdi->penalty = damp->reuse_limit;
323 bdi->suppress_time = 0;
324 bdi->t_updated = t_now;
325
326 /* Need to announce UPDATE once this binfo is usable again. */
327 if (bdi->lastrecord == BGP_RECORD_UPDATE)
328 return 1;
329 else
330 return 0;
331 }
332 }
333 else
334 {
335 t_diff = t_now - bdi->t_updated;
336 bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
337
338 if (bdi->penalty <= damp->reuse_limit / 2.0)
339 {
340 /* release the bdi, bdi->binfo. */
341 bgp_damp_info_free (bdi, 1);
342 return 0;
343 }
344 else
345 bdi->t_updated = t_now;
346 }
347 return 0;
348}
349
350void
351bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
352{
353 struct bgp_info *binfo;
paul718e3742002-12-13 20:15:29 +0000354
355 if (! bdi)
356 return;
357
358 binfo = bdi->binfo;
Paul Jakmafb982c22007-05-04 20:15:47 +0000359 binfo->extra->damp_info = NULL;
paul718e3742002-12-13 20:15:29 +0000360
361 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
362 bgp_reuse_list_delete (bdi);
363 else
364 BGP_DAMP_LIST_DEL (damp, bdi);
365
Paul Jakma1a392d42006-09-07 00:24:49 +0000366 bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED);
paul718e3742002-12-13 20:15:29 +0000367
368 if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
paul200df112005-06-01 11:17:05 +0000369 bgp_info_delete (bdi->rn, binfo);
370
paul718e3742002-12-13 20:15:29 +0000371 XFREE (MTYPE_BGP_DAMP_INFO, bdi);
372}
373
paul94f2b392005-06-28 12:44:16 +0000374static void
paul718e3742002-12-13 20:15:29 +0000375bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
376{
377 double reuse_max_ratio;
paulfd79ac92004-10-13 05:06:08 +0000378 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000379 double j;
380
381 damp->suppress_value = sup;
382 damp->half_life = hlife;
383 damp->reuse_limit = reuse;
384 damp->max_suppress_time = maxsup;
385
386 /* Initialize params per bgp_damp_config. */
387 damp->reuse_index_size = REUSE_ARRAY_SIZE;
388
389 damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life)));
390
391 /* Decay-array computations */
392 damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
393 damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
394 sizeof(double) * (damp->decay_array_size));
395 damp->decay_array[0] = 1.0;
396 damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
397
398 /* Calculate decay values for all possible times */
399 for (i = 2; i < damp->decay_array_size; i++)
400 damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
401
402 /* Reuse-list computations */
403 i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
404 if (i > REUSE_LIST_SIZE || i == 0)
405 i = REUSE_LIST_SIZE;
406 damp->reuse_list_size = i;
407
408 damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
409 damp->reuse_list_size
410 * sizeof (struct bgp_reuse_node *));
paul718e3742002-12-13 20:15:29 +0000411
412 /* Reuse-array computations */
Stephen Hemmingerfac9c6b2010-08-05 10:26:30 -0700413 damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
paul718e3742002-12-13 20:15:29 +0000414 sizeof(int) * damp->reuse_index_size);
paul718e3742002-12-13 20:15:29 +0000415
416 reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
417 j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
418 if ( reuse_max_ratio > j && j != 0 )
419 reuse_max_ratio = j;
420
421 damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
422
423 for (i = 0; i < damp->reuse_index_size; i++)
424 {
425 damp->reuse_index[i] =
426 (int)(((double)damp->half_life / DELTA_REUSE)
427 * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
428 }
429}
430
431int
paulfd79ac92004-10-13 05:06:08 +0000432bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
433 unsigned int reuse, unsigned int suppress, time_t max)
paul718e3742002-12-13 20:15:29 +0000434{
435 if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
436 {
437 if (damp->half_life == half
438 && damp->reuse_limit == reuse
439 && damp->suppress_value == suppress
440 && damp->max_suppress_time == max)
441 return 0;
442 bgp_damp_disable (bgp, afi, safi);
443 }
444
445 SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
446 bgp_damp_parameter_set (half, reuse, suppress, max);
447
448 /* Register reuse timer. */
449 if (! damp->t_reuse)
450 damp->t_reuse =
Donald Sharp774914f2015-10-14 08:50:39 -0400451 thread_add_timer (bm->master, bgp_reuse_timer, NULL, DELTA_REUSE);
paul718e3742002-12-13 20:15:29 +0000452
453 return 0;
454}
455
paul94f2b392005-06-28 12:44:16 +0000456static void
paul718e3742002-12-13 20:15:29 +0000457bgp_damp_config_clean (struct bgp_damp_config *damp)
458{
459 /* Free decay array */
460 XFREE (MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
461
462 /* Free reuse index array */
463 XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
464
465 /* Free reuse list array. */
466 XFREE (MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
467}
468
469/* Clean all the bgp_damp_info stored in reuse_list. */
470void
paul94f2b392005-06-28 12:44:16 +0000471bgp_damp_info_clean (void)
paul718e3742002-12-13 20:15:29 +0000472{
paulfd79ac92004-10-13 05:06:08 +0000473 unsigned int i;
paul718e3742002-12-13 20:15:29 +0000474 struct bgp_damp_info *bdi, *next;
475
476 damp->reuse_offset = 0;
477
478 for (i = 0; i < damp->reuse_list_size; i++)
479 {
480 if (! damp->reuse_list[i])
481 continue;
482
483 for (bdi = damp->reuse_list[i]; bdi; bdi = next)
484 {
485 next = bdi->next;
486 bgp_damp_info_free (bdi, 1);
487 }
488 damp->reuse_list[i] = NULL;
489 }
490
491 for (bdi = damp->no_reuse_list; bdi; bdi = next)
492 {
493 next = bdi->next;
494 bgp_damp_info_free (bdi, 1);
495 }
496 damp->no_reuse_list = NULL;
497}
498
499int
500bgp_damp_disable (struct bgp *bgp, afi_t afi, safi_t safi)
501{
Jorge Boncompte [DTI2]fa4094a2012-04-13 13:46:09 +0200502 /* If it wasn't enabled, there's nothing to do. */
503 if (! CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
504 return 0;
505
paul718e3742002-12-13 20:15:29 +0000506 /* Cancel reuse thread. */
507 if (damp->t_reuse )
508 thread_cancel (damp->t_reuse);
509 damp->t_reuse = NULL;
510
511 /* Clean BGP dampening information. */
512 bgp_damp_info_clean ();
513
514 /* Clear configuration */
515 bgp_damp_config_clean (&bgp_damp_cfg);
516
517 UNSET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
518 return 0;
519}
520
Stephen Hemmingerf3019af2008-08-17 17:51:47 +0100521void
paul718e3742002-12-13 20:15:29 +0000522bgp_config_write_damp (struct vty *vty)
523{
Stephen Hemmingerf3019af2008-08-17 17:51:47 +0100524 if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE*60
525 && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
526 && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
527 && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
528 vty_out (vty, " bgp dampening%s", VTY_NEWLINE);
529 else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE*60
530 && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
531 && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
532 && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4)
David Lamparteref008d22015-03-03 08:48:11 +0100533 vty_out (vty, " bgp dampening %lld%s",
534 bgp_damp_cfg.half_life/60LL,
Stephen Hemmingerf3019af2008-08-17 17:51:47 +0100535 VTY_NEWLINE);
536 else
David Lamparteref008d22015-03-03 08:48:11 +0100537 vty_out (vty, " bgp dampening %lld %d %d %lld%s",
538 bgp_damp_cfg.half_life/60LL,
Stephen Hemmingerf3019af2008-08-17 17:51:47 +0100539 bgp_damp_cfg.reuse_limit,
540 bgp_damp_cfg.suppress_value,
David Lamparteref008d22015-03-03 08:48:11 +0100541 bgp_damp_cfg.max_suppress_time/60LL,
Stephen Hemmingerf3019af2008-08-17 17:51:47 +0100542 VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000543}
544
Stephen Hemmingere9dc9f22009-05-15 10:19:31 -0700545static const char *
paulfd79ac92004-10-13 05:06:08 +0000546bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len)
paul718e3742002-12-13 20:15:29 +0000547{
548 time_t reuse_time = 0;
549 struct tm *tm = NULL;
550
551 if (penalty > damp->reuse_limit)
552 {
553 reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1]))));
554
555 if (reuse_time > damp->max_suppress_time)
556 reuse_time = damp->max_suppress_time;
557
558 tm = gmtime (&reuse_time);
559 }
560 else
561 reuse_time = 0;
562
563 /* Making formatted timer strings. */
564#define ONE_DAY_SECOND 60*60*24
565#define ONE_WEEK_SECOND 60*60*24*7
566 if (reuse_time == 0)
567 snprintf (buf, len, "00:00:00");
568 else if (reuse_time < ONE_DAY_SECOND)
569 snprintf (buf, len, "%02d:%02d:%02d",
570 tm->tm_hour, tm->tm_min, tm->tm_sec);
571 else if (reuse_time < ONE_WEEK_SECOND)
572 snprintf (buf, len, "%dd%02dh%02dm",
573 tm->tm_yday, tm->tm_hour, tm->tm_min);
574 else
575 snprintf (buf, len, "%02dw%dd%02dh",
576 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
577
578 return buf;
579}
580
581void
582bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo)
583{
584 struct bgp_damp_info *bdi;
585 time_t t_now, t_diff;
586 char timebuf[BGP_UPTIME_LEN];
587 int penalty;
588
Paul Jakmafb982c22007-05-04 20:15:47 +0000589 if (!binfo->extra)
590 return;
591
paul718e3742002-12-13 20:15:29 +0000592 /* BGP dampening information. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000593 bdi = binfo->extra->damp_info;
paul718e3742002-12-13 20:15:29 +0000594
595 /* If dampening is not enabled or there is no dampening information,
596 return immediately. */
597 if (! damp || ! bdi)
598 return;
599
600 /* Calculate new penalty. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300601 t_now = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000602 t_diff = t_now - bdi->t_updated;
603 penalty = bgp_damp_decay (t_diff, bdi->penalty);
604
605 vty_out (vty, " Dampinfo: penalty %d, flapped %d times in %s",
606 penalty, bdi->flap,
607 peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN));
608
609 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
610 && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
611 vty_out (vty, ", reuse in %s",
612 bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN));
613
614 vty_out (vty, "%s", VTY_NEWLINE);
615}
616
Stephen Hemmingere9dc9f22009-05-15 10:19:31 -0700617const char *
Chris Caputo50aef6f2009-06-23 06:06:49 +0000618bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
619 char *timebuf, size_t len)
paul718e3742002-12-13 20:15:29 +0000620{
621 struct bgp_damp_info *bdi;
622 time_t t_now, t_diff;
paul718e3742002-12-13 20:15:29 +0000623 int penalty;
Paul Jakmafb982c22007-05-04 20:15:47 +0000624
625 if (!binfo->extra)
626 return NULL;
627
paul718e3742002-12-13 20:15:29 +0000628 /* BGP dampening information. */
Paul Jakmafb982c22007-05-04 20:15:47 +0000629 bdi = binfo->extra->damp_info;
paul718e3742002-12-13 20:15:29 +0000630
631 /* If dampening is not enabled or there is no dampening information,
632 return immediately. */
633 if (! damp || ! bdi)
634 return NULL;
635
636 /* Calculate new penalty. */
Stephen Hemminger65957882010-01-15 16:22:10 +0300637 t_now = bgp_clock ();
paul718e3742002-12-13 20:15:29 +0000638 t_diff = t_now - bdi->t_updated;
639 penalty = bgp_damp_decay (t_diff, bdi->penalty);
640
Chris Caputo50aef6f2009-06-23 06:06:49 +0000641 return bgp_get_reuse_time (penalty, timebuf, len);
paul718e3742002-12-13 20:15:29 +0000642}
Balaji06bd4202015-03-16 16:55:29 +0000643
644int
645bgp_show_dampening_parameters (struct vty *vty, afi_t afi, safi_t safi)
646{
647 struct bgp *bgp;
648 bgp = bgp_get_default();
649
650 if (bgp == NULL)
651 {
652 vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
653 return CMD_WARNING;
654 }
655
656 if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
657 {
658 vty_out (vty, "Half-life time: %ld min%s",
659 damp->half_life / 60, VTY_NEWLINE);
660 vty_out (vty, "Reuse penalty: %d%s",
661 damp->reuse_limit, VTY_NEWLINE);
662 vty_out (vty, "Suppress penalty: %d%s",
663 damp->suppress_value, VTY_NEWLINE);
664 vty_out (vty, "Max suppress time: %ld min%s",
665 damp->max_suppress_time / 60, VTY_NEWLINE);
666 vty_out (vty, "Max supress penalty: %u%s",
667 damp->ceiling, VTY_NEWLINE);
668 vty_out (vty, "%s", VTY_NEWLINE);
669 }
670 else
671 vty_out (vty, "dampening not enabled for %s%s",
672 afi == AFI_IP ? "IPv4" : "IPv6", VTY_NEWLINE);
673
674 return CMD_SUCCESS;
675}