]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_damp.c
*: remove VTYNL, part 1 of 6
[mirror_frr.git] / bgpd / bgp_damp.c
CommitLineData
718e3744 1/* BGP flap dampening
896014f4
DL
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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
718e3744 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"
3f9c7369 29#include "queue.h"
039f3a34 30#include "filter.h"
718e3744 31
32#include "bgpd/bgpd.h"
33#include "bgpd/bgp_damp.h"
34#include "bgpd/bgp_table.h"
35#include "bgpd/bgp_route.h"
36#include "bgpd/bgp_attr.h"
37#include "bgpd/bgp_advertise.h"
38
39/* Global variable to access damping configuration */
40struct bgp_damp_config bgp_damp_cfg;
e9dc9f24 41static struct bgp_damp_config *damp = &bgp_damp_cfg;
718e3744 42
43/* Utility macro to add and delete BGP dampening information to no
44 used list. */
45#define BGP_DAMP_LIST_ADD(N,A) BGP_INFO_ADD(N,A,no_reuse_list)
46#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list)
6b0655a2 47
718e3744 48/* Calculate reuse list index by penalty value. */
49static int
50bgp_reuse_index (int penalty)
51{
fd79ac91 52 unsigned int i;
718e3744 53 int index;
54
55 i = (int)(((double) penalty / damp->reuse_limit - 1.0) * damp->scale_factor);
56
57 if ( i >= damp->reuse_index_size )
58 i = damp->reuse_index_size - 1;
59
60 index = damp->reuse_index[i] - damp->reuse_index[0];
61
62 return (damp->reuse_offset + index) % damp->reuse_list_size;
63}
64
65/* Add BGP dampening information to reuse list. */
66static void
67bgp_reuse_list_add (struct bgp_damp_info *bdi)
68{
69 int index;
70
71 index = bdi->index = bgp_reuse_index (bdi->penalty);
72
73 bdi->prev = NULL;
74 bdi->next = damp->reuse_list[index];
75 if (damp->reuse_list[index])
76 damp->reuse_list[index]->prev = bdi;
77 damp->reuse_list[index] = bdi;
78}
79
80/* Delete BGP dampening information from reuse list. */
81static void
82bgp_reuse_list_delete (struct bgp_damp_info *bdi)
83{
84 if (bdi->next)
85 bdi->next->prev = bdi->prev;
86 if (bdi->prev)
87 bdi->prev->next = bdi->next;
88 else
89 damp->reuse_list[bdi->index] = bdi->next;
90}
6b0655a2 91
718e3744 92/* Return decayed penalty value. */
93int
94bgp_damp_decay (time_t tdiff, int penalty)
95{
fd79ac91 96 unsigned int i;
718e3744 97
98 i = (int) ((double) tdiff / DELTA_T);
99
100 if (i == 0)
101 return penalty;
102
103 if (i >= damp->decay_array_size)
104 return 0;
105
106 return (int) (penalty * damp->decay_array[i]);
107}
108
109/* Handler of reuse timer event. Each route in the current reuse-list
110 is evaluated. RFC2439 Section 4.8.7. */
94f2b392 111static int
718e3744 112bgp_reuse_timer (struct thread *t)
113{
114 struct bgp_damp_info *bdi;
115 struct bgp_damp_info *next;
116 time_t t_now, t_diff;
41200856 117
718e3744 118 damp->t_reuse = NULL;
66e78ae6
QY
119 thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
120 &damp->t_reuse);
718e3744 121
65957886 122 t_now = bgp_clock ();
718e3744 123
124 /* 1. save a pointer to the current zeroth queue head and zero the
125 list head entry. */
126 bdi = damp->reuse_list[damp->reuse_offset];
127 damp->reuse_list[damp->reuse_offset] = NULL;
128
129 /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
130 rotating the circular queue of list-heads. */
131 damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
132
133 /* 3. if ( the saved list head pointer is non-empty ) */
134 for (; bdi; bdi = next)
135 {
41200856 136 struct bgp *bgp = bdi->binfo->peer->bgp;
137
718e3744 138 next = bdi->next;
139
140 /* Set t-diff = t-now - t-updated. */
141 t_diff = t_now - bdi->t_updated;
142
143 /* Set figure-of-merit = figure-of-merit * decay-array-ok [t-diff] */
144 bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
145
146 /* Set t-updated = t-now. */
147 bdi->t_updated = t_now;
148
149 /* if (figure-of-merit < reuse). */
150 if (bdi->penalty < damp->reuse_limit)
151 {
152 /* Reuse the route. */
1a392d46 153 bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_DAMPED);
718e3744 154 bdi->suppress_time = 0;
155
156 if (bdi->lastrecord == BGP_RECORD_UPDATE)
157 {
1a392d46 158 bgp_info_unset_flag (bdi->rn, bdi->binfo, BGP_INFO_HISTORY);
718e3744 159 bgp_aggregate_increment (bgp, &bdi->rn->p, bdi->binfo,
160 bdi->afi, bdi->safi);
161 bgp_process (bgp, bdi->rn, bdi->afi, bdi->safi);
162 }
163
164 if (bdi->penalty <= damp->reuse_limit / 2.0)
165 bgp_damp_info_free (bdi, 1);
166 else
167 BGP_DAMP_LIST_ADD (damp, bdi);
168 }
169 else
170 /* Re-insert into another list (See RFC2439 Section 4.8.6). */
171 bgp_reuse_list_add (bdi);
172 }
173
174 return 0;
175}
176
177/* A route becomes unreachable (RFC2439 Section 4.8.2). */
178int
179bgp_damp_withdraw (struct bgp_info *binfo, struct bgp_node *rn,
180 afi_t afi, safi_t safi, int attr_change)
181{
182 time_t t_now;
fb982c25 183 struct bgp_damp_info *bdi = NULL;
718e3744 184 double last_penalty = 0;
185
65957886 186 t_now = bgp_clock ();
718e3744 187
188 /* Processing Unreachable Messages. */
fb982c25
PJ
189 if (binfo->extra)
190 bdi = binfo->extra->damp_info;
191
718e3744 192 if (bdi == NULL)
193 {
194 /* If there is no previous stability history. */
195
196 /* RFC2439 said:
197 1. allocate a damping structure.
198 2. set figure-of-merit = 1.
199 3. withdraw the route. */
200
201 bdi = XCALLOC (MTYPE_BGP_DAMP_INFO, sizeof (struct bgp_damp_info));
202 bdi->binfo = binfo;
203 bdi->rn = rn;
204 bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY);
205 bdi->flap = 1;
206 bdi->start_time = t_now;
207 bdi->suppress_time = 0;
208 bdi->index = -1;
209 bdi->afi = afi;
210 bdi->safi = safi;
fb982c25 211 (bgp_info_extra_get (binfo))->damp_info = bdi;
718e3744 212 BGP_DAMP_LIST_ADD (damp, bdi);
213 }
214 else
215 {
216 last_penalty = bdi->penalty;
217
218 /* 1. Set t-diff = t-now - t-updated. */
219 bdi->penalty =
220 (bgp_damp_decay (t_now - bdi->t_updated, bdi->penalty)
221 + (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY));
222
223 if (bdi->penalty > damp->ceiling)
224 bdi->penalty = damp->ceiling;
225
226 bdi->flap++;
227 }
228
1a392d46
PJ
229 assert ((rn == bdi->rn) && (binfo == bdi->binfo));
230
718e3744 231 bdi->lastrecord = BGP_RECORD_WITHDRAW;
232 bdi->t_updated = t_now;
233
234 /* Make this route as historical status. */
1a392d46 235 bgp_info_set_flag (rn, binfo, BGP_INFO_HISTORY);
718e3744 236
237 /* Remove the route from a reuse list if it is on one. */
238 if (CHECK_FLAG (bdi->binfo->flags, BGP_INFO_DAMPED))
239 {
240 /* If decay rate isn't equal to 0, reinsert brn. */
241 if (bdi->penalty != last_penalty)
242 {
243 bgp_reuse_list_delete (bdi);
244 bgp_reuse_list_add (bdi);
245 }
246 return BGP_DAMP_SUPPRESSED;
247 }
248
249 /* If not suppressed before, do annonunce this withdraw and
250 insert into reuse_list. */
251 if (bdi->penalty >= damp->suppress_value)
252 {
1a392d46 253 bgp_info_set_flag (rn, binfo, BGP_INFO_DAMPED);
718e3744 254 bdi->suppress_time = t_now;
255 BGP_DAMP_LIST_DEL (damp, bdi);
256 bgp_reuse_list_add (bdi);
257 }
258
259 return BGP_DAMP_USED;
260}
261
262int
263bgp_damp_update (struct bgp_info *binfo, struct bgp_node *rn,
264 afi_t afi, safi_t safi)
265{
266 time_t t_now;
267 struct bgp_damp_info *bdi;
268 int status;
269
fb982c25 270 if (!binfo->extra || !((bdi = binfo->extra->damp_info)))
718e3744 271 return BGP_DAMP_USED;
272
65957886 273 t_now = bgp_clock ();
1a392d46 274 bgp_info_unset_flag (rn, binfo, BGP_INFO_HISTORY);
718e3744 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 {
1a392d46 285 bgp_info_unset_flag (rn, binfo, BGP_INFO_DAMPED);
718e3744 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. */
303int
304bgp_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;
fb982c25
PJ
308
309 assert (binfo->extra && binfo->extra->damp_info);
310
65957886 311 t_now = bgp_clock ();
fb982c25 312 bdi = binfo->extra->damp_info;
718e3744 313
314 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
315 {
316 t_diff = t_now - bdi->suppress_time;
317
318 if (t_diff >= damp->max_suppress_time)
319 {
1a392d46 320 bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_DAMPED);
718e3744 321 bgp_reuse_list_delete (bdi);
322 BGP_DAMP_LIST_ADD (damp, bdi);
323 bdi->penalty = damp->reuse_limit;
324 bdi->suppress_time = 0;
325 bdi->t_updated = t_now;
326
327 /* Need to announce UPDATE once this binfo is usable again. */
328 if (bdi->lastrecord == BGP_RECORD_UPDATE)
329 return 1;
330 else
331 return 0;
332 }
333 }
334 else
335 {
336 t_diff = t_now - bdi->t_updated;
337 bdi->penalty = bgp_damp_decay (t_diff, bdi->penalty);
338
339 if (bdi->penalty <= damp->reuse_limit / 2.0)
340 {
341 /* release the bdi, bdi->binfo. */
342 bgp_damp_info_free (bdi, 1);
343 return 0;
344 }
345 else
346 bdi->t_updated = t_now;
347 }
348 return 0;
349}
350
351void
352bgp_damp_info_free (struct bgp_damp_info *bdi, int withdraw)
353{
354 struct bgp_info *binfo;
718e3744 355
356 if (! bdi)
357 return;
358
359 binfo = bdi->binfo;
fb982c25 360 binfo->extra->damp_info = NULL;
718e3744 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
1a392d46 367 bgp_info_unset_flag (bdi->rn, binfo, BGP_INFO_HISTORY|BGP_INFO_DAMPED);
718e3744 368
369 if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
200df115 370 bgp_info_delete (bdi->rn, binfo);
371
718e3744 372 XFREE (MTYPE_BGP_DAMP_INFO, bdi);
373}
374
94f2b392 375static void
718e3744 376bgp_damp_parameter_set (int hlife, int reuse, int sup, int maxsup)
377{
378 double reuse_max_ratio;
fd79ac91 379 unsigned int i;
718e3744 380 double j;
381
382 damp->suppress_value = sup;
383 damp->half_life = hlife;
384 damp->reuse_limit = reuse;
385 damp->max_suppress_time = maxsup;
386
387 /* Initialize params per bgp_damp_config. */
388 damp->reuse_index_size = REUSE_ARRAY_SIZE;
389
390 damp->ceiling = (int)(damp->reuse_limit * (pow(2, (double)damp->max_suppress_time/damp->half_life)));
391
392 /* Decay-array computations */
393 damp->decay_array_size = ceil ((double) damp->max_suppress_time / DELTA_T);
394 damp->decay_array = XMALLOC (MTYPE_BGP_DAMP_ARRAY,
395 sizeof(double) * (damp->decay_array_size));
396 damp->decay_array[0] = 1.0;
397 damp->decay_array[1] = exp ((1.0/((double)damp->half_life/DELTA_T)) * log(0.5));
398
399 /* Calculate decay values for all possible times */
400 for (i = 2; i < damp->decay_array_size; i++)
401 damp->decay_array[i] = damp->decay_array[i-1] * damp->decay_array[1];
402
403 /* Reuse-list computations */
404 i = ceil ((double)damp->max_suppress_time / DELTA_REUSE) + 1;
405 if (i > REUSE_LIST_SIZE || i == 0)
406 i = REUSE_LIST_SIZE;
407 damp->reuse_list_size = i;
408
409 damp->reuse_list = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
410 damp->reuse_list_size
411 * sizeof (struct bgp_reuse_node *));
718e3744 412
413 /* Reuse-array computations */
fac9c6b6 414 damp->reuse_index = XCALLOC (MTYPE_BGP_DAMP_ARRAY,
718e3744 415 sizeof(int) * damp->reuse_index_size);
718e3744 416
417 reuse_max_ratio = (double)damp->ceiling/damp->reuse_limit;
418 j = (exp((double)damp->max_suppress_time/damp->half_life) * log10(2.0));
419 if ( reuse_max_ratio > j && j != 0 )
420 reuse_max_ratio = j;
421
422 damp->scale_factor = (double)damp->reuse_index_size/(reuse_max_ratio - 1);
423
424 for (i = 0; i < damp->reuse_index_size; i++)
425 {
426 damp->reuse_index[i] =
427 (int)(((double)damp->half_life / DELTA_REUSE)
428 * log10 (1.0 / (damp->reuse_limit * ( 1.0 + ((double)i/damp->scale_factor)))) / log10(0.5));
429 }
430}
431
432int
fd79ac91 433bgp_damp_enable (struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
434 unsigned int reuse, unsigned int suppress, time_t max)
718e3744 435{
436 if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
437 {
438 if (damp->half_life == half
439 && damp->reuse_limit == reuse
440 && damp->suppress_value == suppress
441 && damp->max_suppress_time == max)
442 return 0;
443 bgp_damp_disable (bgp, afi, safi);
444 }
445
446 SET_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
447 bgp_damp_parameter_set (half, reuse, suppress, max);
448
449 /* Register reuse timer. */
ffa2c898
QY
450 thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
451 &damp->t_reuse);
718e3744 452
453 return 0;
454}
455
94f2b392 456static void
718e3744 457bgp_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
94f2b392 471bgp_damp_info_clean (void)
718e3744 472{
fd79ac91 473 unsigned int i;
718e3744 474 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{
fa4094ac
JBD
502 /* 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
718e3744 506 /* 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
f3019aff 521void
718e3744 522bgp_config_write_damp (struct vty *vty)
523{
f3019aff
SH
524 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)
5c7571d4 528 vty_out (vty, " bgp dampening\n");
f3019aff
SH
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)
5c7571d4 533 vty_out (vty, " bgp dampening %lld\n",
96ade3ed 534 bgp_damp_cfg.half_life / 60LL);
f3019aff 535 else
5c7571d4 536 vty_out (vty, " bgp dampening %lld %d %d %lld\n",
8f2c16aa 537 bgp_damp_cfg.half_life/60LL,
f3019aff
SH
538 bgp_damp_cfg.reuse_limit,
539 bgp_damp_cfg.suppress_value,
96ade3ed 540 bgp_damp_cfg.max_suppress_time / 60LL);
718e3744 541}
542
e9dc9f24 543static const char *
856ca177 544bgp_get_reuse_time (unsigned int penalty, char *buf, size_t len, u_char use_json, json_object *json)
718e3744 545{
546 time_t reuse_time = 0;
547 struct tm *tm = NULL;
856ca177 548 int time_store = 0;
718e3744 549
550 if (penalty > damp->reuse_limit)
551 {
552 reuse_time = (int) (DELTA_T * ((log((double)damp->reuse_limit/penalty))/(log(damp->decay_array[1]))));
553
554 if (reuse_time > damp->max_suppress_time)
555 reuse_time = damp->max_suppress_time;
556
557 tm = gmtime (&reuse_time);
558 }
559 else
560 reuse_time = 0;
561
562 /* Making formatted timer strings. */
563#define ONE_DAY_SECOND 60*60*24
564#define ONE_WEEK_SECOND 60*60*24*7
565 if (reuse_time == 0)
856ca177
MS
566 {
567 if (use_json)
568 json_object_int_add(json, "reuseTimerMsecs", 0);
569 else
570 snprintf (buf, len, "00:00:00");
571 }
718e3744 572 else if (reuse_time < ONE_DAY_SECOND)
856ca177
MS
573 {
574 if (use_json)
575 {
576 time_store = (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec);
577 json_object_int_add(json, "reuseTimerMsecs", time_store);
578 }
579 else
580 snprintf (buf, len, "%02d:%02d:%02d",
581 tm->tm_hour, tm->tm_min, tm->tm_sec);
582 }
718e3744 583 else if (reuse_time < ONE_WEEK_SECOND)
856ca177
MS
584 {
585 if (use_json)
586 {
587 time_store = (86400000 * tm->tm_yday) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec);
588 json_object_int_add(json, "reuseTimerMsecs", time_store);
589 }
590 else
591 snprintf (buf, len, "%dd%02dh%02dm",
592 tm->tm_yday, tm->tm_hour, tm->tm_min);
593 }
718e3744 594 else
856ca177
MS
595 {
596 if (use_json)
597 {
598 time_store = (604800000 * tm->tm_yday/7) + (86400000 * (tm->tm_yday - ((tm->tm_yday/7) * 7))) + (3600000 * tm->tm_hour) + (60000 * tm->tm_min) + (1000 * tm->tm_sec);
599 json_object_int_add(json, "reuseTimerMsecs", time_store);
600 }
601 else
602 snprintf (buf, len, "%02dw%dd%02dh",
603 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
604 }
718e3744 605
606 return buf;
607}
608
609void
b05a1c8b
DS
610bgp_damp_info_vty (struct vty *vty, struct bgp_info *binfo,
611 json_object *json_path)
718e3744 612{
613 struct bgp_damp_info *bdi;
614 time_t t_now, t_diff;
615 char timebuf[BGP_UPTIME_LEN];
616 int penalty;
617
fb982c25
PJ
618 if (!binfo->extra)
619 return;
620
718e3744 621 /* BGP dampening information. */
fb982c25 622 bdi = binfo->extra->damp_info;
718e3744 623
624 /* If dampening is not enabled or there is no dampening information,
625 return immediately. */
626 if (! damp || ! bdi)
627 return;
628
629 /* Calculate new penalty. */
65957886 630 t_now = bgp_clock ();
718e3744 631 t_diff = t_now - bdi->t_updated;
632 penalty = bgp_damp_decay (t_diff, bdi->penalty);
633
b05a1c8b
DS
634 if (json_path)
635 {
62d6dca0
DS
636 json_object_int_add(json_path, "dampeningPenalty", penalty);
637 json_object_int_add(json_path, "dampeningFlapCount", bdi->flap);
856ca177 638 peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 1, json_path);
b05a1c8b
DS
639
640 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
641 && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
856ca177 642 bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 1, json_path);
b05a1c8b
DS
643 }
644 else
645 {
646 vty_out (vty, " Dampinfo: penalty %d, flapped %d times in %s",
647 penalty, bdi->flap,
856ca177 648 peer_uptime (bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, json_path));
718e3744 649
b05a1c8b
DS
650 if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
651 && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
652 vty_out (vty, ", reuse in %s",
856ca177 653 bgp_get_reuse_time (penalty, timebuf, BGP_UPTIME_LEN, 0, json_path));
718e3744 654
6d3c2ed4 655 vty_out (vty, "\n");
b05a1c8b 656 }
718e3744 657}
658
e9dc9f24 659const char *
50aef6f3 660bgp_damp_reuse_time_vty (struct vty *vty, struct bgp_info *binfo,
856ca177 661 char *timebuf, size_t len, u_char use_json, json_object *json)
718e3744 662{
663 struct bgp_damp_info *bdi;
664 time_t t_now, t_diff;
718e3744 665 int penalty;
fb982c25
PJ
666
667 if (!binfo->extra)
668 return NULL;
669
718e3744 670 /* BGP dampening information. */
fb982c25 671 bdi = binfo->extra->damp_info;
718e3744 672
673 /* If dampening is not enabled or there is no dampening information,
674 return immediately. */
675 if (! damp || ! bdi)
676 return NULL;
677
678 /* Calculate new penalty. */
65957886 679 t_now = bgp_clock ();
718e3744 680 t_diff = t_now - bdi->t_updated;
681 penalty = bgp_damp_decay (t_diff, bdi->penalty);
682
856ca177 683 return bgp_get_reuse_time (penalty, timebuf, len, use_json, json);
718e3744 684}
9914e022
B
685
686int
687bgp_show_dampening_parameters (struct vty *vty, afi_t afi, safi_t safi)
688{
689 struct bgp *bgp;
690 bgp = bgp_get_default();
691
692 if (bgp == NULL)
693 {
5c7571d4 694 vty_out (vty, "No BGP process is configured\n");
9914e022
B
695 return CMD_WARNING;
696 }
697
698 if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
699 {
5c7571d4 700 vty_out (vty, "Half-life time: %lld min\n",
96ade3ed 701 (long long)damp->half_life / 60);
5c7571d4 702 vty_out (vty, "Reuse penalty: %d\n",
96ade3ed 703 damp->reuse_limit);
5c7571d4 704 vty_out (vty, "Suppress penalty: %d\n",
96ade3ed 705 damp->suppress_value);
5c7571d4 706 vty_out (vty, "Max suppress time: %lld min\n",
96ade3ed 707 (long long)damp->max_suppress_time / 60);
5c7571d4 708 vty_out (vty, "Max supress penalty: %u\n",
96ade3ed 709 damp->ceiling);
6d3c2ed4 710 vty_out (vty, "\n");
9914e022
B
711 }
712 else
5c7571d4 713 vty_out (vty, "dampening not enabled for %s\n",
96ade3ed 714 afi == AFI_IP ? "IPv4" : "IPv6");
9914e022
B
715
716 return CMD_SUCCESS;
717}