]>
git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_damp.c
2 * Copyright (C) 2001 IP Infusion Inc.
4 * This file is part of GNU Zebra.
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
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.
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
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"
39 const char *get_afi_safi_str(afi_t afi
, safi_t safi
, bool for_json
);
41 /* Global variable to access damping configuration */
42 static struct bgp_damp_config damp
[AFI_MAX
][SAFI_MAX
];
44 /* Utility macro to add and delete BGP dampening information to no
46 #define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
47 #define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
49 /* Calculate reuse list index by penalty value. */
50 static int bgp_reuse_index(int penalty
, struct bgp_damp_config
*bdc
)
56 * reuse_limit can't be zero, this is for Coverity
57 * to bypass division by zero test.
59 assert(bdc
->reuse_limit
);
61 i
= (int)(((double)penalty
/ bdc
->reuse_limit
- 1.0)
64 if (i
>= bdc
->reuse_index_size
)
65 i
= bdc
->reuse_index_size
- 1;
67 index
= bdc
->reuse_index
[i
] - bdc
->reuse_index
[0];
69 return (bdc
->reuse_offset
+ index
) % bdc
->reuse_list_size
;
72 /* Add BGP dampening information to reuse list. */
73 static void bgp_reuse_list_add(struct bgp_damp_info
*bdi
,
74 struct bgp_damp_config
*bdc
)
78 index
= bdi
->index
= bgp_reuse_index(bdi
->penalty
, bdc
);
81 bdi
->next
= bdc
->reuse_list
[index
];
82 if (bdc
->reuse_list
[index
])
83 bdc
->reuse_list
[index
]->prev
= bdi
;
84 bdc
->reuse_list
[index
] = bdi
;
87 /* Delete BGP dampening information from reuse list. */
88 static void bgp_reuse_list_delete(struct bgp_damp_info
*bdi
,
89 struct bgp_damp_config
*bdc
)
92 bdi
->next
->prev
= bdi
->prev
;
94 bdi
->prev
->next
= bdi
->next
;
96 bdc
->reuse_list
[bdi
->index
] = bdi
->next
;
99 /* Return decayed penalty value. */
100 int bgp_damp_decay(time_t tdiff
, int penalty
, struct bgp_damp_config
*bdc
)
104 i
= (int)((double)tdiff
/ DELTA_T
);
109 if (i
>= bdc
->decay_array_size
)
112 return (int)(penalty
* bdc
->decay_array
[i
]);
115 /* Handler of reuse timer event. Each route in the current reuse-list
116 is evaluated. RFC2439 Section 4.8.7. */
117 static int bgp_reuse_timer(struct thread
*t
)
119 struct bgp_damp_info
*bdi
;
120 struct bgp_damp_info
*next
;
121 time_t t_now
, t_diff
;
123 struct bgp_damp_config
*bdc
= THREAD_ARG(t
);
126 thread_add_timer(bm
->master
, bgp_reuse_timer
, bdc
, DELTA_REUSE
,
131 /* 1. save a pointer to the current zeroth queue head and zero the
133 bdi
= bdc
->reuse_list
[bdc
->reuse_offset
];
134 bdc
->reuse_list
[bdc
->reuse_offset
] = NULL
;
136 /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
137 rotating the circular queue of list-heads. */
138 bdc
->reuse_offset
= (bdc
->reuse_offset
+ 1) % bdc
->reuse_list_size
;
140 /* 3. if ( the saved list head pointer is non-empty ) */
141 for (; bdi
; bdi
= next
) {
142 struct bgp
*bgp
= bdi
->path
->peer
->bgp
;
146 /* Set t-diff = t-now - t-updated. */
147 t_diff
= t_now
- bdi
->t_updated
;
149 /* Set figure-of-merit = figure-of-merit * decay-array-ok
151 bdi
->penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
153 /* Set t-updated = t-now. */
154 bdi
->t_updated
= t_now
;
156 /* if (figure-of-merit < reuse). */
157 if (bdi
->penalty
< bdc
->reuse_limit
) {
158 /* Reuse the route. */
159 bgp_path_info_unset_flag(bdi
->dest
, bdi
->path
,
161 bdi
->suppress_time
= 0;
163 if (bdi
->lastrecord
== BGP_RECORD_UPDATE
) {
164 bgp_path_info_unset_flag(bdi
->dest
, bdi
->path
,
166 bgp_aggregate_increment(
167 bgp
, bgp_dest_get_prefix(bdi
->dest
),
168 bdi
->path
, bdi
->afi
, bdi
->safi
);
169 bgp_process(bgp
, bdi
->dest
, bdi
->afi
,
173 if (bdi
->penalty
<= bdc
->reuse_limit
/ 2.0)
174 bgp_damp_info_free(bdi
, 1, bdc
->afi
, bdc
->safi
);
176 BGP_DAMP_LIST_ADD(bdc
, bdi
);
178 /* Re-insert into another list (See RFC2439 Section
180 bgp_reuse_list_add(bdi
, bdc
);
186 /* A route becomes unreachable (RFC2439 Section 4.8.2). */
187 int bgp_damp_withdraw(struct bgp_path_info
*path
, struct bgp_dest
*dest
,
188 afi_t afi
, safi_t safi
, int attr_change
)
191 struct bgp_damp_info
*bdi
= NULL
;
192 unsigned int last_penalty
= 0;
193 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
197 /* Processing Unreachable Messages. */
199 bdi
= path
->extra
->damp_info
;
202 /* If there is no previous stability history. */
205 1. allocate a damping structure.
206 2. set figure-of-merit = 1.
207 3. withdraw the route. */
209 bdi
= XCALLOC(MTYPE_BGP_DAMP_INFO
,
210 sizeof(struct bgp_damp_info
));
214 (attr_change
? DEFAULT_PENALTY
/ 2 : DEFAULT_PENALTY
);
216 bdi
->start_time
= t_now
;
217 bdi
->suppress_time
= 0;
221 (bgp_path_info_extra_get(path
))->damp_info
= bdi
;
222 BGP_DAMP_LIST_ADD(bdc
, bdi
);
224 last_penalty
= bdi
->penalty
;
226 /* 1. Set t-diff = t-now - t-updated. */
227 bdi
->penalty
= (bgp_damp_decay(t_now
- bdi
->t_updated
,
229 + (attr_change
? DEFAULT_PENALTY
/ 2
232 if (bdi
->penalty
> bdc
->ceiling
)
233 bdi
->penalty
= bdc
->ceiling
;
238 assert((dest
== bdi
->dest
) && (path
== bdi
->path
));
240 bdi
->lastrecord
= BGP_RECORD_WITHDRAW
;
241 bdi
->t_updated
= t_now
;
243 /* Make this route as historical status. */
244 bgp_path_info_set_flag(dest
, path
, BGP_PATH_HISTORY
);
246 /* Remove the route from a reuse list if it is on one. */
247 if (CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)) {
248 /* If decay rate isn't equal to 0, reinsert brn. */
249 if (bdi
->penalty
!= last_penalty
&& bdi
->index
>= 0) {
250 bgp_reuse_list_delete(bdi
, bdc
);
251 bgp_reuse_list_add(bdi
, bdc
);
253 return BGP_DAMP_SUPPRESSED
;
256 /* If not suppressed before, do annonunce this withdraw and
257 insert into reuse_list. */
258 if (bdi
->penalty
>= bdc
->suppress_value
) {
259 bgp_path_info_set_flag(dest
, path
, BGP_PATH_DAMPED
);
260 bdi
->suppress_time
= t_now
;
261 BGP_DAMP_LIST_DEL(bdc
, bdi
);
262 bgp_reuse_list_add(bdi
, bdc
);
265 return BGP_DAMP_USED
;
268 int bgp_damp_update(struct bgp_path_info
*path
, struct bgp_dest
*dest
,
269 afi_t afi
, safi_t safi
)
272 struct bgp_damp_info
*bdi
;
274 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
276 if (!path
->extra
|| !((bdi
= path
->extra
->damp_info
)))
277 return BGP_DAMP_USED
;
280 bgp_path_info_unset_flag(dest
, path
, BGP_PATH_HISTORY
);
282 bdi
->lastrecord
= BGP_RECORD_UPDATE
;
284 bgp_damp_decay(t_now
- bdi
->t_updated
, bdi
->penalty
, bdc
);
286 if (!CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)
287 && (bdi
->penalty
< bdc
->suppress_value
))
288 status
= BGP_DAMP_USED
;
289 else if (CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)
290 && (bdi
->penalty
< bdc
->reuse_limit
)) {
291 bgp_path_info_unset_flag(dest
, path
, BGP_PATH_DAMPED
);
292 bgp_reuse_list_delete(bdi
, bdc
);
293 BGP_DAMP_LIST_ADD(bdc
, bdi
);
294 bdi
->suppress_time
= 0;
295 status
= BGP_DAMP_USED
;
297 status
= BGP_DAMP_SUPPRESSED
;
299 if (bdi
->penalty
> bdc
->reuse_limit
/ 2.0)
300 bdi
->t_updated
= t_now
;
302 bgp_damp_info_free(bdi
, 0, afi
, safi
);
307 void bgp_damp_info_free(struct bgp_damp_info
*bdi
, int withdraw
, afi_t afi
,
310 struct bgp_path_info
*path
;
311 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
317 path
->extra
->damp_info
= NULL
;
319 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
320 bgp_reuse_list_delete(bdi
, bdc
);
322 BGP_DAMP_LIST_DEL(bdc
, bdi
);
324 bgp_path_info_unset_flag(bdi
->dest
, path
,
325 BGP_PATH_HISTORY
| BGP_PATH_DAMPED
);
327 if (bdi
->lastrecord
== BGP_RECORD_WITHDRAW
&& withdraw
)
328 bgp_path_info_delete(bdi
->dest
, path
);
330 XFREE(MTYPE_BGP_DAMP_INFO
, bdi
);
333 static void bgp_damp_parameter_set(int hlife
, int reuse
, int sup
, int maxsup
,
334 struct bgp_damp_config
*bdc
)
336 double reuse_max_ratio
;
340 bdc
->suppress_value
= sup
;
341 bdc
->half_life
= hlife
;
342 bdc
->reuse_limit
= reuse
;
343 bdc
->max_suppress_time
= maxsup
;
345 /* Initialize params per bgp_damp_config. */
346 bdc
->reuse_index_size
= REUSE_ARRAY_SIZE
;
348 bdc
->ceiling
= (int)(bdc
->reuse_limit
349 * (pow(2, (double)bdc
->max_suppress_time
352 /* Decay-array computations */
353 bdc
->decay_array_size
= ceil((double)bdc
->max_suppress_time
/ DELTA_T
);
354 bdc
->decay_array
= XMALLOC(MTYPE_BGP_DAMP_ARRAY
,
355 sizeof(double) * (bdc
->decay_array_size
));
356 bdc
->decay_array
[0] = 1.0;
357 bdc
->decay_array
[1] =
358 exp((1.0 / ((double)bdc
->half_life
/ DELTA_T
)) * log(0.5));
360 /* Calculate decay values for all possible times */
361 for (i
= 2; i
< bdc
->decay_array_size
; i
++)
362 bdc
->decay_array
[i
] =
363 bdc
->decay_array
[i
- 1] * bdc
->decay_array
[1];
365 /* Reuse-list computations */
366 i
= ceil((double)bdc
->max_suppress_time
/ DELTA_REUSE
) + 1;
367 if (i
> REUSE_LIST_SIZE
|| i
== 0)
369 bdc
->reuse_list_size
= i
;
372 XCALLOC(MTYPE_BGP_DAMP_ARRAY
,
373 bdc
->reuse_list_size
* sizeof(struct bgp_reuse_node
*));
375 /* Reuse-array computations */
376 bdc
->reuse_index
= XCALLOC(MTYPE_BGP_DAMP_ARRAY
,
377 sizeof(int) * bdc
->reuse_index_size
);
379 reuse_max_ratio
= (double)bdc
->ceiling
/ bdc
->reuse_limit
;
380 j
= (exp((double)bdc
->max_suppress_time
/ bdc
->half_life
) * log10(2.0));
381 if (reuse_max_ratio
> j
&& j
!= 0)
385 (double)bdc
->reuse_index_size
/ (reuse_max_ratio
- 1);
387 for (i
= 0; i
< bdc
->reuse_index_size
; i
++) {
388 bdc
->reuse_index
[i
] =
389 (int)(((double)bdc
->half_life
/ DELTA_REUSE
)
393 + ((double)i
/ bdc
->scale_factor
))))
398 int bgp_damp_enable(struct bgp
*bgp
, afi_t afi
, safi_t safi
, time_t half
,
399 unsigned int reuse
, unsigned int suppress
, time_t max
)
401 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
403 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)) {
404 if (bdc
->half_life
== half
&& bdc
->reuse_limit
== reuse
405 && bdc
->suppress_value
== suppress
406 && bdc
->max_suppress_time
== max
)
408 bgp_damp_disable(bgp
, afi
, safi
);
411 SET_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
);
412 bgp_damp_parameter_set(half
, reuse
, suppress
, max
, bdc
);
414 /* Register reuse timer. */
415 thread_add_timer(bm
->master
, bgp_reuse_timer
, bdc
, DELTA_REUSE
,
421 static void bgp_damp_config_clean(struct bgp_damp_config
*bdc
)
423 /* Free decay array */
424 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->decay_array
);
425 bdc
->decay_array_size
= 0;
427 /* Free reuse index array */
428 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->reuse_index
);
429 bdc
->reuse_index_size
= 0;
431 /* Free reuse list array. */
432 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->reuse_list
);
433 bdc
->reuse_list_size
= 0;
436 /* Clean all the bgp_damp_info stored in reuse_list. */
437 void bgp_damp_info_clean(afi_t afi
, safi_t safi
)
440 struct bgp_damp_info
*bdi
, *next
;
441 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
443 bdc
->reuse_offset
= 0;
445 for (i
= 0; i
< bdc
->reuse_list_size
; i
++) {
446 if (!bdc
->reuse_list
[i
])
449 for (bdi
= bdc
->reuse_list
[i
]; bdi
; bdi
= next
) {
451 bgp_damp_info_free(bdi
, 1, afi
, safi
);
453 bdc
->reuse_list
[i
] = NULL
;
456 for (bdi
= bdc
->no_reuse_list
; bdi
; bdi
= next
) {
458 bgp_damp_info_free(bdi
, 1, afi
, safi
);
460 bdc
->no_reuse_list
= NULL
;
463 int bgp_damp_disable(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
465 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
466 /* If it wasn't enabled, there's nothing to do. */
467 if (!CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
))
470 /* Cancel reuse thread. */
472 thread_cancel(bdc
->t_reuse
);
475 /* Clean BGP dampening information. */
476 bgp_damp_info_clean(afi
, safi
);
478 /* Clear configuration */
479 bgp_damp_config_clean(bdc
);
481 UNSET_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
);
485 void bgp_config_write_damp(struct vty
*vty
, afi_t afi
, safi_t safi
)
487 if (damp
[afi
][safi
].half_life
== DEFAULT_HALF_LIFE
* 60
488 && damp
[afi
][safi
].reuse_limit
== DEFAULT_REUSE
489 && damp
[afi
][safi
].suppress_value
== DEFAULT_SUPPRESS
490 && damp
[afi
][safi
].max_suppress_time
491 == damp
[afi
][safi
].half_life
* 4)
492 vty_out(vty
, " bgp dampening\n");
493 else if (damp
[afi
][safi
].half_life
!= DEFAULT_HALF_LIFE
* 60
494 && damp
[afi
][safi
].reuse_limit
== DEFAULT_REUSE
495 && damp
[afi
][safi
].suppress_value
== DEFAULT_SUPPRESS
496 && damp
[afi
][safi
].max_suppress_time
497 == damp
[afi
][safi
].half_life
* 4)
498 vty_out(vty
, " bgp dampening %lld\n",
499 damp
[afi
][safi
].half_life
/ 60LL);
501 vty_out(vty
, " bgp dampening %lld %d %d %lld\n",
502 damp
[afi
][safi
].half_life
/ 60LL,
503 damp
[afi
][safi
].reuse_limit
,
504 damp
[afi
][safi
].suppress_value
,
505 damp
[afi
][safi
].max_suppress_time
/ 60LL);
508 static const char *bgp_get_reuse_time(unsigned int penalty
, char *buf
,
509 size_t len
, afi_t afi
, safi_t safi
,
510 bool use_json
, json_object
*json
)
512 time_t reuse_time
= 0;
516 if (penalty
> damp
[afi
][safi
].reuse_limit
) {
517 reuse_time
= (int)(DELTA_T
518 * ((log((double)damp
[afi
][safi
].reuse_limit
520 / (log(damp
[afi
][safi
].decay_array
[1]))));
522 if (reuse_time
> damp
[afi
][safi
].max_suppress_time
)
523 reuse_time
= damp
[afi
][safi
].max_suppress_time
;
525 gmtime_r(&reuse_time
, &tm
);
529 /* Making formatted timer strings. */
530 if (reuse_time
== 0) {
532 json_object_int_add(json
, "reuseTimerMsecs", 0);
534 snprintf(buf
, len
, "00:00:00");
535 } else if (reuse_time
< ONE_DAY_SECOND
) {
537 time_store
= (3600000 * tm
.tm_hour
)
538 + (60000 * tm
.tm_min
)
539 + (1000 * tm
.tm_sec
);
540 json_object_int_add(json
, "reuseTimerMsecs",
543 snprintf(buf
, len
, "%02d:%02d:%02d", tm
.tm_hour
,
544 tm
.tm_min
, tm
.tm_sec
);
545 } else if (reuse_time
< ONE_WEEK_SECOND
) {
547 time_store
= (86400000 * tm
.tm_yday
)
548 + (3600000 * tm
.tm_hour
)
549 + (60000 * tm
.tm_min
)
550 + (1000 * tm
.tm_sec
);
551 json_object_int_add(json
, "reuseTimerMsecs",
554 snprintf(buf
, len
, "%dd%02dh%02dm", tm
.tm_yday
,
555 tm
.tm_hour
, tm
.tm_min
);
559 (604800000 * tm
.tm_yday
/ 7)
561 * (tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7)))
562 + (3600000 * tm
.tm_hour
) + (60000 * tm
.tm_min
)
563 + (1000 * tm
.tm_sec
);
564 json_object_int_add(json
, "reuseTimerMsecs",
567 snprintf(buf
, len
, "%02dw%dd%02dh", tm
.tm_yday
/ 7,
568 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
575 void bgp_damp_info_vty(struct vty
*vty
, struct bgp_path_info
*path
, afi_t afi
,
576 safi_t safi
, json_object
*json_path
)
578 struct bgp_damp_info
*bdi
;
579 time_t t_now
, t_diff
;
580 char timebuf
[BGP_UPTIME_LEN
];
582 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
587 /* BGP dampening information. */
588 bdi
= path
->extra
->damp_info
;
590 /* If dampening is not enabled or there is no dampening information,
591 return immediately. */
595 /* Calculate new penalty. */
597 t_diff
= t_now
- bdi
->t_updated
;
598 penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
601 json_object_int_add(json_path
, "dampeningPenalty", penalty
);
602 json_object_int_add(json_path
, "dampeningFlapCount", bdi
->flap
);
603 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, 1,
606 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
607 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
608 bgp_get_reuse_time(penalty
, timebuf
, BGP_UPTIME_LEN
,
609 afi
, safi
, 1, json_path
);
612 " Dampinfo: penalty %d, flapped %d times in %s",
614 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, 0,
617 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
618 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
619 vty_out(vty
, ", reuse in %s",
620 bgp_get_reuse_time(penalty
, timebuf
,
621 BGP_UPTIME_LEN
, afi
, safi
, 0,
628 const char *bgp_damp_reuse_time_vty(struct vty
*vty
, struct bgp_path_info
*path
,
629 char *timebuf
, size_t len
, afi_t afi
,
630 safi_t safi
, bool use_json
,
633 struct bgp_damp_info
*bdi
;
634 time_t t_now
, t_diff
;
636 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
641 /* BGP dampening information. */
642 bdi
= path
->extra
->damp_info
;
644 /* If dampening is not enabled or there is no dampening information,
645 return immediately. */
649 /* Calculate new penalty. */
651 t_diff
= t_now
- bdi
->t_updated
;
652 penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
654 return bgp_get_reuse_time(penalty
, timebuf
, len
, afi
, safi
, use_json
,
658 static int bgp_print_dampening_parameters(struct bgp
*bgp
, struct vty
*vty
,
659 afi_t afi
, safi_t safi
)
661 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)) {
662 vty_out(vty
, "Half-life time: %lld min\n",
663 (long long)damp
[afi
][safi
].half_life
/ 60);
664 vty_out(vty
, "Reuse penalty: %d\n",
665 damp
[afi
][safi
].reuse_limit
);
666 vty_out(vty
, "Suppress penalty: %d\n",
667 damp
[afi
][safi
].suppress_value
);
668 vty_out(vty
, "Max suppress time: %lld min\n",
669 (long long)damp
[afi
][safi
].max_suppress_time
/ 60);
670 vty_out(vty
, "Max suppress penalty: %u\n",
671 damp
[afi
][safi
].ceiling
);
674 vty_out(vty
, "dampening not enabled for %s\n",
675 get_afi_safi_str(afi
, safi
, false));
680 int bgp_show_dampening_parameters(struct vty
*vty
, afi_t afi
, safi_t safi
,
684 bgp
= bgp_get_default();
687 vty_out(vty
, "No BGP process is configured\n");
691 if (!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
))
692 return bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
);
694 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
695 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
696 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
698 FOREACH_SAFI (safi
) {
699 if (strmatch(get_afi_safi_str(afi
, safi
, true),
703 if (!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
))
704 vty_out(vty
, "\nFor address family: %s\n\n",
705 get_afi_safi_str(afi
, safi
, false));
707 bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
);
710 FOREACH_AFI_SAFI (afi
, safi
) {
711 if (strmatch(get_afi_safi_str(afi
, safi
, true),
715 if (!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
))
716 vty_out(vty
, "\nFor address family: %s\n",
717 get_afi_safi_str(afi
, safi
, false));
719 bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
);