]>
git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_damp.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2001 IP Infusion Inc.
17 #include "bgpd/bgpd.h"
18 #include "bgpd/bgp_damp.h"
19 #include "bgpd/bgp_table.h"
20 #include "bgpd/bgp_route.h"
21 #include "bgpd/bgp_attr.h"
22 #include "bgpd/bgp_advertise.h"
23 #include "bgpd/bgp_vty.h"
25 /* Global variable to access damping configuration */
26 static struct bgp_damp_config damp
[AFI_MAX
][SAFI_MAX
];
28 /* Utility macro to add and delete BGP dampening information to no
30 #define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
31 #define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
33 /* Calculate reuse list index by penalty value. */
34 static int bgp_reuse_index(int penalty
, struct bgp_damp_config
*bdc
)
40 * reuse_limit can't be zero, this is for Coverity
41 * to bypass division by zero test.
43 assert(bdc
->reuse_limit
);
45 i
= (int)(((double)penalty
/ bdc
->reuse_limit
- 1.0)
48 if (i
>= bdc
->reuse_index_size
)
49 i
= bdc
->reuse_index_size
- 1;
51 index
= bdc
->reuse_index
[i
] - bdc
->reuse_index
[0];
53 return (bdc
->reuse_offset
+ index
) % bdc
->reuse_list_size
;
56 /* Add BGP dampening information to reuse list. */
57 static void bgp_reuse_list_add(struct bgp_damp_info
*bdi
,
58 struct bgp_damp_config
*bdc
)
62 index
= bdi
->index
= bgp_reuse_index(bdi
->penalty
, bdc
);
65 bdi
->next
= bdc
->reuse_list
[index
];
66 if (bdc
->reuse_list
[index
])
67 bdc
->reuse_list
[index
]->prev
= bdi
;
68 bdc
->reuse_list
[index
] = bdi
;
71 /* Delete BGP dampening information from reuse list. */
72 static void bgp_reuse_list_delete(struct bgp_damp_info
*bdi
,
73 struct bgp_damp_config
*bdc
)
76 bdi
->next
->prev
= bdi
->prev
;
78 bdi
->prev
->next
= bdi
->next
;
80 bdc
->reuse_list
[bdi
->index
] = bdi
->next
;
83 /* Return decayed penalty value. */
84 int bgp_damp_decay(time_t tdiff
, int penalty
, struct bgp_damp_config
*bdc
)
88 i
= (int)((double)tdiff
/ DELTA_T
);
93 if (i
>= bdc
->decay_array_size
)
96 return (int)(penalty
* bdc
->decay_array
[i
]);
99 /* Handler of reuse timer event. Each route in the current reuse-list
100 is evaluated. RFC2439 Section 4.8.7. */
101 static void bgp_reuse_timer(struct event
*t
)
103 struct bgp_damp_info
*bdi
;
104 struct bgp_damp_info
*next
;
105 time_t t_now
, t_diff
;
107 struct bgp_damp_config
*bdc
= EVENT_ARG(t
);
110 event_add_timer(bm
->master
, bgp_reuse_timer
, bdc
, DELTA_REUSE
,
113 t_now
= monotime(NULL
);
115 /* 1. save a pointer to the current zeroth queue head and zero the
117 bdi
= bdc
->reuse_list
[bdc
->reuse_offset
];
118 bdc
->reuse_list
[bdc
->reuse_offset
] = NULL
;
120 /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
121 rotating the circular queue of list-heads. */
122 bdc
->reuse_offset
= (bdc
->reuse_offset
+ 1) % bdc
->reuse_list_size
;
124 /* 3. if ( the saved list head pointer is non-empty ) */
125 for (; bdi
; bdi
= next
) {
126 struct bgp
*bgp
= bdi
->path
->peer
->bgp
;
130 /* Set t-diff = t-now - t-updated. */
131 t_diff
= t_now
- bdi
->t_updated
;
133 /* Set figure-of-merit = figure-of-merit * decay-array-ok
135 bdi
->penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
137 /* Set t-updated = t-now. */
138 bdi
->t_updated
= t_now
;
140 /* if (figure-of-merit < reuse). */
141 if (bdi
->penalty
< bdc
->reuse_limit
) {
142 /* Reuse the route. */
143 bgp_path_info_unset_flag(bdi
->dest
, bdi
->path
,
145 bdi
->suppress_time
= 0;
147 if (bdi
->lastrecord
== BGP_RECORD_UPDATE
) {
148 bgp_path_info_unset_flag(bdi
->dest
, bdi
->path
,
150 bgp_aggregate_increment(
151 bgp
, bgp_dest_get_prefix(bdi
->dest
),
152 bdi
->path
, bdi
->afi
, bdi
->safi
);
153 bgp_process(bgp
, bdi
->dest
, bdi
->afi
,
157 if (bdi
->penalty
<= bdc
->reuse_limit
/ 2.0)
158 bgp_damp_info_free(bdi
, 1, bdc
->afi
, bdc
->safi
);
160 BGP_DAMP_LIST_ADD(bdc
, bdi
);
162 /* Re-insert into another list (See RFC2439 Section
164 bgp_reuse_list_add(bdi
, bdc
);
168 /* A route becomes unreachable (RFC2439 Section 4.8.2). */
169 int bgp_damp_withdraw(struct bgp_path_info
*path
, struct bgp_dest
*dest
,
170 afi_t afi
, safi_t safi
, int attr_change
)
173 struct bgp_damp_info
*bdi
= NULL
;
174 unsigned int last_penalty
= 0;
175 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
177 t_now
= monotime(NULL
);
179 /* Processing Unreachable Messages. */
181 bdi
= path
->extra
->damp_info
;
184 /* If there is no previous stability history. */
187 1. allocate a damping structure.
188 2. set figure-of-merit = 1.
189 3. withdraw the route. */
191 bdi
= XCALLOC(MTYPE_BGP_DAMP_INFO
,
192 sizeof(struct bgp_damp_info
));
196 (attr_change
? DEFAULT_PENALTY
/ 2 : DEFAULT_PENALTY
);
198 bdi
->start_time
= t_now
;
199 bdi
->suppress_time
= 0;
203 (bgp_path_info_extra_get(path
))->damp_info
= bdi
;
204 BGP_DAMP_LIST_ADD(bdc
, bdi
);
206 last_penalty
= bdi
->penalty
;
208 /* 1. Set t-diff = t-now - t-updated. */
209 bdi
->penalty
= (bgp_damp_decay(t_now
- bdi
->t_updated
,
211 + (attr_change
? DEFAULT_PENALTY
/ 2
214 if (bdi
->penalty
> bdc
->ceiling
)
215 bdi
->penalty
= bdc
->ceiling
;
220 assert((dest
== bdi
->dest
) && (path
== bdi
->path
));
222 bdi
->lastrecord
= BGP_RECORD_WITHDRAW
;
223 bdi
->t_updated
= t_now
;
225 /* Make this route as historical status. */
226 bgp_path_info_set_flag(dest
, path
, BGP_PATH_HISTORY
);
228 /* Remove the route from a reuse list if it is on one. */
229 if (CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)) {
230 /* If decay rate isn't equal to 0, reinsert brn. */
231 if (bdi
->penalty
!= last_penalty
&& bdi
->index
>= 0) {
232 bgp_reuse_list_delete(bdi
, bdc
);
233 bgp_reuse_list_add(bdi
, bdc
);
235 return BGP_DAMP_SUPPRESSED
;
238 /* If not suppressed before, do annonunce this withdraw and
239 insert into reuse_list. */
240 if (bdi
->penalty
>= bdc
->suppress_value
) {
241 bgp_path_info_set_flag(dest
, path
, BGP_PATH_DAMPED
);
242 bdi
->suppress_time
= t_now
;
243 BGP_DAMP_LIST_DEL(bdc
, bdi
);
244 bgp_reuse_list_add(bdi
, bdc
);
247 return BGP_DAMP_USED
;
250 int bgp_damp_update(struct bgp_path_info
*path
, struct bgp_dest
*dest
,
251 afi_t afi
, safi_t safi
)
254 struct bgp_damp_info
*bdi
;
256 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
258 if (!path
->extra
|| !((bdi
= path
->extra
->damp_info
)))
259 return BGP_DAMP_USED
;
261 t_now
= monotime(NULL
);
262 bgp_path_info_unset_flag(dest
, path
, BGP_PATH_HISTORY
);
264 bdi
->lastrecord
= BGP_RECORD_UPDATE
;
266 bgp_damp_decay(t_now
- bdi
->t_updated
, bdi
->penalty
, bdc
);
268 if (!CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)
269 && (bdi
->penalty
< bdc
->suppress_value
))
270 status
= BGP_DAMP_USED
;
271 else if (CHECK_FLAG(bdi
->path
->flags
, BGP_PATH_DAMPED
)
272 && (bdi
->penalty
< bdc
->reuse_limit
)) {
273 bgp_path_info_unset_flag(dest
, path
, BGP_PATH_DAMPED
);
274 bgp_reuse_list_delete(bdi
, bdc
);
275 BGP_DAMP_LIST_ADD(bdc
, bdi
);
276 bdi
->suppress_time
= 0;
277 status
= BGP_DAMP_USED
;
279 status
= BGP_DAMP_SUPPRESSED
;
281 if (bdi
->penalty
> bdc
->reuse_limit
/ 2.0)
282 bdi
->t_updated
= t_now
;
284 bgp_damp_info_free(bdi
, 0, afi
, safi
);
289 void bgp_damp_info_free(struct bgp_damp_info
*bdi
, int withdraw
, afi_t afi
,
292 struct bgp_path_info
*path
;
293 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
299 path
->extra
->damp_info
= NULL
;
301 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
))
302 bgp_reuse_list_delete(bdi
, bdc
);
304 BGP_DAMP_LIST_DEL(bdc
, bdi
);
306 bgp_path_info_unset_flag(bdi
->dest
, path
,
307 BGP_PATH_HISTORY
| BGP_PATH_DAMPED
);
309 if (bdi
->lastrecord
== BGP_RECORD_WITHDRAW
&& withdraw
)
310 bgp_path_info_delete(bdi
->dest
, path
);
312 XFREE(MTYPE_BGP_DAMP_INFO
, bdi
);
315 static void bgp_damp_parameter_set(time_t hlife
, unsigned int reuse
,
316 unsigned int sup
, time_t maxsup
,
317 struct bgp_damp_config
*bdc
)
319 double reuse_max_ratio
;
323 bdc
->suppress_value
= sup
;
324 bdc
->half_life
= hlife
;
325 bdc
->reuse_limit
= reuse
;
326 bdc
->max_suppress_time
= maxsup
;
328 /* Initialize params per bgp_damp_config. */
329 bdc
->reuse_index_size
= REUSE_ARRAY_SIZE
;
331 bdc
->ceiling
= (int)(bdc
->reuse_limit
332 * (pow(2, (double)bdc
->max_suppress_time
335 /* Decay-array computations */
336 bdc
->decay_array_size
= ceil((double)bdc
->max_suppress_time
/ DELTA_T
);
337 bdc
->decay_array
= XMALLOC(MTYPE_BGP_DAMP_ARRAY
,
338 sizeof(double) * (bdc
->decay_array_size
));
339 bdc
->decay_array
[0] = 1.0;
340 bdc
->decay_array
[1] =
341 exp((1.0 / ((double)bdc
->half_life
/ DELTA_T
)) * log(0.5));
343 /* Calculate decay values for all possible times */
344 for (i
= 2; i
< bdc
->decay_array_size
; i
++)
345 bdc
->decay_array
[i
] =
346 bdc
->decay_array
[i
- 1] * bdc
->decay_array
[1];
348 /* Reuse-list computations */
349 i
= ceil((double)bdc
->max_suppress_time
/ DELTA_REUSE
) + 1;
350 if (i
> REUSE_LIST_SIZE
|| i
== 0)
352 bdc
->reuse_list_size
= i
;
355 XCALLOC(MTYPE_BGP_DAMP_ARRAY
,
356 bdc
->reuse_list_size
* sizeof(struct bgp_reuse_node
*));
358 /* Reuse-array computations */
359 bdc
->reuse_index
= XCALLOC(MTYPE_BGP_DAMP_ARRAY
,
360 sizeof(int) * bdc
->reuse_index_size
);
362 reuse_max_ratio
= (double)bdc
->ceiling
/ bdc
->reuse_limit
;
363 j
= (exp((double)bdc
->max_suppress_time
/ bdc
->half_life
) * log10(2.0));
364 if (reuse_max_ratio
> j
&& j
!= 0)
368 (double)bdc
->reuse_index_size
/ (reuse_max_ratio
- 1);
370 for (i
= 0; i
< bdc
->reuse_index_size
; i
++) {
371 bdc
->reuse_index
[i
] =
372 (int)(((double)bdc
->half_life
/ DELTA_REUSE
)
376 + ((double)i
/ bdc
->scale_factor
))))
381 int bgp_damp_enable(struct bgp
*bgp
, afi_t afi
, safi_t safi
, time_t half
,
382 unsigned int reuse
, unsigned int suppress
, time_t max
)
384 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
386 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)) {
387 if (bdc
->half_life
== half
&& bdc
->reuse_limit
== reuse
388 && bdc
->suppress_value
== suppress
389 && bdc
->max_suppress_time
== max
)
391 bgp_damp_disable(bgp
, afi
, safi
);
394 SET_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
);
395 bgp_damp_parameter_set(half
, reuse
, suppress
, max
, bdc
);
397 /* Register reuse timer. */
398 event_add_timer(bm
->master
, bgp_reuse_timer
, bdc
, DELTA_REUSE
,
404 static void bgp_damp_config_clean(struct bgp_damp_config
*bdc
)
406 /* Free decay array */
407 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->decay_array
);
408 bdc
->decay_array_size
= 0;
410 /* Free reuse index array */
411 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->reuse_index
);
412 bdc
->reuse_index_size
= 0;
414 /* Free reuse list array. */
415 XFREE(MTYPE_BGP_DAMP_ARRAY
, bdc
->reuse_list
);
416 bdc
->reuse_list_size
= 0;
419 /* Clean all the bgp_damp_info stored in reuse_list. */
420 void bgp_damp_info_clean(afi_t afi
, safi_t safi
)
423 struct bgp_damp_info
*bdi
, *next
;
424 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
426 bdc
->reuse_offset
= 0;
428 for (i
= 0; i
< bdc
->reuse_list_size
; i
++) {
429 if (!bdc
->reuse_list
[i
])
432 for (bdi
= bdc
->reuse_list
[i
]; bdi
; bdi
= next
) {
434 bgp_damp_info_free(bdi
, 1, afi
, safi
);
436 bdc
->reuse_list
[i
] = NULL
;
439 for (bdi
= bdc
->no_reuse_list
; bdi
; bdi
= next
) {
441 bgp_damp_info_free(bdi
, 1, afi
, safi
);
443 bdc
->no_reuse_list
= NULL
;
446 int bgp_damp_disable(struct bgp
*bgp
, afi_t afi
, safi_t safi
)
448 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
449 /* If it wasn't enabled, there's nothing to do. */
450 if (!CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
))
453 /* Cancel reuse event. */
454 EVENT_OFF(bdc
->t_reuse
);
456 /* Clean BGP dampening information. */
457 bgp_damp_info_clean(afi
, safi
);
459 /* Clear configuration */
460 bgp_damp_config_clean(bdc
);
462 UNSET_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
);
466 void bgp_config_write_damp(struct vty
*vty
, afi_t afi
, safi_t safi
)
468 if (damp
[afi
][safi
].half_life
== DEFAULT_HALF_LIFE
* 60
469 && damp
[afi
][safi
].reuse_limit
== DEFAULT_REUSE
470 && damp
[afi
][safi
].suppress_value
== DEFAULT_SUPPRESS
471 && damp
[afi
][safi
].max_suppress_time
472 == damp
[afi
][safi
].half_life
* 4)
473 vty_out(vty
, " bgp dampening\n");
474 else if (damp
[afi
][safi
].half_life
!= DEFAULT_HALF_LIFE
* 60
475 && damp
[afi
][safi
].reuse_limit
== DEFAULT_REUSE
476 && damp
[afi
][safi
].suppress_value
== DEFAULT_SUPPRESS
477 && damp
[afi
][safi
].max_suppress_time
478 == damp
[afi
][safi
].half_life
* 4)
479 vty_out(vty
, " bgp dampening %lld\n",
480 damp
[afi
][safi
].half_life
/ 60LL);
482 vty_out(vty
, " bgp dampening %lld %d %d %lld\n",
483 damp
[afi
][safi
].half_life
/ 60LL,
484 damp
[afi
][safi
].reuse_limit
,
485 damp
[afi
][safi
].suppress_value
,
486 damp
[afi
][safi
].max_suppress_time
/ 60LL);
489 static const char *bgp_get_reuse_time(unsigned int penalty
, char *buf
,
490 size_t len
, afi_t afi
, safi_t safi
,
491 bool use_json
, json_object
*json
)
493 time_t reuse_time
= 0;
497 if (penalty
> damp
[afi
][safi
].reuse_limit
) {
498 reuse_time
= (int)(DELTA_T
499 * ((log((double)damp
[afi
][safi
].reuse_limit
501 / (log(damp
[afi
][safi
].decay_array
[1]))));
503 if (reuse_time
> damp
[afi
][safi
].max_suppress_time
)
504 reuse_time
= damp
[afi
][safi
].max_suppress_time
;
506 gmtime_r(&reuse_time
, &tm
);
510 /* Making formatted timer strings. */
511 if (reuse_time
== 0) {
513 json_object_int_add(json
, "reuseTimerMsecs", 0);
515 snprintf(buf
, len
, "00:00:00");
516 } else if (reuse_time
< ONE_DAY_SECOND
) {
518 time_store
= (3600000 * tm
.tm_hour
)
519 + (60000 * tm
.tm_min
)
520 + (1000 * tm
.tm_sec
);
521 json_object_int_add(json
, "reuseTimerMsecs",
524 snprintf(buf
, len
, "%02d:%02d:%02d", tm
.tm_hour
,
525 tm
.tm_min
, tm
.tm_sec
);
526 } else if (reuse_time
< ONE_WEEK_SECOND
) {
528 time_store
= (86400000 * tm
.tm_yday
)
529 + (3600000 * tm
.tm_hour
)
530 + (60000 * tm
.tm_min
)
531 + (1000 * tm
.tm_sec
);
532 json_object_int_add(json
, "reuseTimerMsecs",
535 snprintf(buf
, len
, "%dd%02dh%02dm", tm
.tm_yday
,
536 tm
.tm_hour
, tm
.tm_min
);
540 (604800000 * tm
.tm_yday
/ 7)
542 * (tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7)))
543 + (3600000 * tm
.tm_hour
) + (60000 * tm
.tm_min
)
544 + (1000 * tm
.tm_sec
);
545 json_object_int_add(json
, "reuseTimerMsecs",
548 snprintf(buf
, len
, "%02dw%dd%02dh", tm
.tm_yday
/ 7,
549 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
556 void bgp_damp_info_vty(struct vty
*vty
, struct bgp_path_info
*path
, afi_t afi
,
557 safi_t safi
, json_object
*json_path
)
559 struct bgp_damp_info
*bdi
;
560 time_t t_now
, t_diff
;
561 char timebuf
[BGP_UPTIME_LEN
];
563 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
568 /* BGP dampening information. */
569 bdi
= path
->extra
->damp_info
;
571 /* If dampening is not enabled or there is no dampening information,
572 return immediately. */
576 /* Calculate new penalty. */
577 t_now
= monotime(NULL
);
578 t_diff
= t_now
- bdi
->t_updated
;
579 penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
582 json_object_int_add(json_path
, "dampeningPenalty", penalty
);
583 json_object_int_add(json_path
, "dampeningFlapCount", bdi
->flap
);
584 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, 1,
587 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
588 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
589 bgp_get_reuse_time(penalty
, timebuf
, BGP_UPTIME_LEN
,
590 afi
, safi
, 1, json_path
);
593 " Dampinfo: penalty %d, flapped %d times in %s",
595 peer_uptime(bdi
->start_time
, timebuf
, BGP_UPTIME_LEN
, 0,
598 if (CHECK_FLAG(path
->flags
, BGP_PATH_DAMPED
)
599 && !CHECK_FLAG(path
->flags
, BGP_PATH_HISTORY
))
600 vty_out(vty
, ", reuse in %s",
601 bgp_get_reuse_time(penalty
, timebuf
,
602 BGP_UPTIME_LEN
, afi
, safi
, 0,
609 const char *bgp_damp_reuse_time_vty(struct vty
*vty
, struct bgp_path_info
*path
,
610 char *timebuf
, size_t len
, afi_t afi
,
611 safi_t safi
, bool use_json
,
614 struct bgp_damp_info
*bdi
;
615 time_t t_now
, t_diff
;
617 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
622 /* BGP dampening information. */
623 bdi
= path
->extra
->damp_info
;
625 /* If dampening is not enabled or there is no dampening information,
626 return immediately. */
630 /* Calculate new penalty. */
631 t_now
= monotime(NULL
);
632 t_diff
= t_now
- bdi
->t_updated
;
633 penalty
= bgp_damp_decay(t_diff
, bdi
->penalty
, bdc
);
635 return bgp_get_reuse_time(penalty
, timebuf
, len
, afi
, safi
, use_json
,
639 static int bgp_print_dampening_parameters(struct bgp
*bgp
, struct vty
*vty
,
640 afi_t afi
, safi_t safi
, bool use_json
)
642 if (CHECK_FLAG(bgp
->af_flags
[afi
][safi
], BGP_CONFIG_DAMPENING
)) {
643 struct bgp_damp_config
*bdc
= &damp
[afi
][safi
];
646 json_object
*json
= json_object_new_object();
648 json_object_int_add(json
, "halfLifeSecs",
650 json_object_int_add(json
, "reusePenalty",
652 json_object_int_add(json
, "suppressPenalty",
653 bdc
->suppress_value
);
654 json_object_int_add(json
, "maxSuppressTimeSecs",
655 bdc
->max_suppress_time
);
656 json_object_int_add(json
, "maxSuppressPenalty",
661 vty_out(vty
, "Half-life time: %lld min\n",
662 (long long)bdc
->half_life
/ 60);
663 vty_out(vty
, "Reuse penalty: %d\n", bdc
->reuse_limit
);
664 vty_out(vty
, "Suppress penalty: %d\n",
665 bdc
->suppress_value
);
666 vty_out(vty
, "Max suppress time: %lld min\n",
667 (long long)bdc
->max_suppress_time
/ 60);
668 vty_out(vty
, "Max suppress penalty: %u\n",
672 } else if (!use_json
)
673 vty_out(vty
, "dampening not enabled for %s\n",
674 get_afi_safi_str(afi
, safi
, false));
679 int bgp_show_dampening_parameters(struct vty
*vty
, afi_t afi
, safi_t safi
,
683 bool use_json
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
685 bgp
= bgp_get_default();
688 vty_out(vty
, "No BGP process is configured\n");
692 if (!CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_ALL
))
693 return bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
,
696 if (CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
)
697 || CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP6
)) {
698 afi
= CHECK_FLAG(show_flags
, BGP_SHOW_OPT_AFI_IP
) ? AFI_IP
700 FOREACH_SAFI (safi
) {
701 if (strmatch(get_afi_safi_str(afi
, safi
, true),
706 vty_out(vty
, "\nFor address family: %s\n\n",
707 get_afi_safi_str(afi
, safi
, false));
709 bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
,
713 FOREACH_AFI_SAFI (afi
, safi
) {
714 if (strmatch(get_afi_safi_str(afi
, safi
, true),
719 vty_out(vty
, "\nFor address family: %s\n",
720 get_afi_safi_str(afi
, safi
, false));
722 bgp_print_dampening_parameters(bgp
, vty
, afi
, safi
,