Merge pull request #9256 from idryzhov/dampening-revert

BGP per-peer dampening revert
This commit is contained in:
Donald Sharp 2021-08-06 10:46:09 -04:00 committed by GitHub
commit 883da9f5ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 198 additions and 1523 deletions

View File

@ -37,76 +37,19 @@
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
static void bgp_reuselist_add(struct reuselist *list,
struct bgp_damp_info *info)
{
assert(info);
SLIST_INSERT_HEAD(list, info, entry);
}
/* Global variable to access damping configuration */
static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
static void bgp_reuselist_del(struct reuselist *list,
struct bgp_damp_info *info)
{
assert(info);
SLIST_REMOVE(list, info, bgp_damp_info, entry);
}
static void bgp_reuselist_switch(struct reuselist *source,
struct bgp_damp_info *info,
struct reuselist *target)
{
assert(source && target && info);
SLIST_REMOVE(source, info, bgp_damp_info, entry);
SLIST_INSERT_HEAD(target, info, entry);
}
static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi)
{
assert(bdi && bdi->config);
if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX)
bgp_reuselist_del(&bdi->config->no_reuse_list, bdi);
else
bgp_reuselist_del(&bdi->config->reuse_list[bdi->index], bdi);
bdi->config = NULL;
}
static void bgp_damp_info_claim(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc)
{
assert(bdc && bdi);
if (bdi->config == NULL) {
bdi->config = bdc;
return;
}
bgp_damp_info_unclaim(bdi);
bdi->config = bdc;
bdi->afi = bdc->afi;
bdi->safi = bdc->safi;
}
struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi,
afi_t afi, safi_t safi)
{
if (!pi)
return NULL;
if (CHECK_FLAG(pi->peer->af_flags[afi][safi],
PEER_FLAG_CONFIG_DAMPENING))
return &pi->peer->damp[afi][safi];
if (peer_group_active(pi->peer))
if (CHECK_FLAG(pi->peer->group->conf->af_flags[afi][safi],
PEER_FLAG_CONFIG_DAMPENING))
return &pi->peer->group->conf->damp[afi][safi];
if (CHECK_FLAG(pi->peer->bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING))
return &pi->peer->bgp->damp[afi][safi];
return NULL;
}
/* Utility macro to add and delete BGP dampening information to no
used list. */
#define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
/* Calculate reuse list index by penalty value. */
static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
{
unsigned int i;
unsigned int index;
int index;
/*
* reuse_limit can't be zero, this is for Coverity
@ -129,28 +72,27 @@ static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
static void bgp_reuse_list_add(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc)
{
bgp_damp_info_claim(bdi, bdc);
bdi->index = bgp_reuse_index(bdi->penalty, bdc);
bgp_reuselist_add(&bdc->reuse_list[bdi->index], bdi);
int index;
index = bdi->index = bgp_reuse_index(bdi->penalty, bdc);
bdi->prev = NULL;
bdi->next = bdc->reuse_list[index];
if (bdc->reuse_list[index])
bdc->reuse_list[index]->prev = bdi;
bdc->reuse_list[index] = bdi;
}
/* Delete BGP dampening information from reuse list. */
static void bgp_reuse_list_delete(struct bgp_damp_info *bdi)
{
bgp_damp_info_unclaim(bdi);
}
static void bgp_no_reuse_list_add(struct bgp_damp_info *bdi,
static void bgp_reuse_list_delete(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc)
{
bgp_damp_info_claim(bdi, bdc);
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
bgp_reuselist_add(&bdc->no_reuse_list, bdi);
}
static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi)
{
bgp_damp_info_unclaim(bdi);
if (bdi->next)
bdi->next->prev = bdi->prev;
if (bdi->prev)
bdi->prev->next = bdi->next;
else
bdc->reuse_list[bdi->index] = bdi->next;
}
/* Return decayed penalty value. */
@ -173,31 +115,32 @@ int bgp_damp_decay(time_t tdiff, int penalty, struct bgp_damp_config *bdc)
is evaluated. RFC2439 Section 4.8.7. */
static int bgp_reuse_timer(struct thread *t)
{
struct bgp_damp_config *bdc = THREAD_ARG(t);
struct bgp_damp_info *bdi;
struct reuselist plist;
struct bgp *bgp;
struct bgp_damp_info *next;
time_t t_now, t_diff;
struct bgp_damp_config *bdc = THREAD_ARG(t);
bdc->t_reuse = NULL;
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
&bdc->t_reuse);
t_now = bgp_clock();
/* 1. save a pointer to the current queue head and zero the list head
* list head entry. */
assert(bdc->reuse_offset < bdc->reuse_list_size);
plist = bdc->reuse_list[bdc->reuse_offset];
SLIST_INIT(&bdc->reuse_list[bdc->reuse_offset]);
/* 1. save a pointer to the current zeroth queue head and zero the
list head entry. */
bdi = bdc->reuse_list[bdc->reuse_offset];
bdc->reuse_list[bdc->reuse_offset] = NULL;
/* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
rotating the circular queue of list-heads. */
bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size;
assert(bdc->reuse_offset < bdc->reuse_list_size);
/* 3. if ( the saved list head pointer is non-empty ) */
while ((bdi = SLIST_FIRST(&plist)) != NULL) {
bgp = bdi->path->peer->bgp;
for (; bdi; bdi = next) {
struct bgp *bgp = bdi->path->peer->bgp;
next = bdi->next;
/* Set t-diff = t-now - t-updated. */
t_diff = t_now - bdi->t_updated;
@ -226,25 +169,16 @@ static int bgp_reuse_timer(struct thread *t)
bdi->safi);
}
if (bdi->penalty <= bdc->reuse_limit / 2.0) {
bgp_reuselist_del(&plist, bdi);
bgp_damp_info_free(bdi, 1);
} else {
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
bgp_reuselist_switch(&plist, bdi,
&bdc->no_reuse_list);
}
} else {
if (bdi->penalty <= bdc->reuse_limit / 2.0)
bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi);
else
BGP_DAMP_LIST_ADD(bdc, bdi);
} else
/* Re-insert into another list (See RFC2439 Section
* 4.8.6). */
bdi->index = bgp_reuse_index(bdi->penalty, bdc);
bgp_reuselist_switch(&plist, bdi,
&bdc->reuse_list[bdi->index]);
}
bgp_reuse_list_add(bdi, bdc);
}
assert(SLIST_EMPTY(&plist));
return 0;
}
@ -255,13 +189,10 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
time_t t_now;
struct bgp_damp_info *bdi = NULL;
unsigned int last_penalty = 0;
struct bgp_damp_config *bdc;
bdc = get_active_bdc_from_pi(path, afi, safi);
if (!bdc)
return BGP_DAMP_USED;
struct bgp_damp_config *bdc = &damp[afi][safi];
t_now = bgp_clock();
/* Processing Unreachable Messages. */
if (path->extra)
bdi = path->extra->damp_info;
@ -283,20 +214,12 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
bdi->flap = 1;
bdi->start_time = t_now;
bdi->suppress_time = 0;
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
bdi->index = -1;
bdi->afi = afi;
bdi->safi = safi;
(bgp_path_info_extra_get(path))->damp_info = bdi;
bgp_no_reuse_list_add(bdi, bdc);
BGP_DAMP_LIST_ADD(bdc, bdi);
} else {
if (bdi->config != bdc) {
bgp_damp_info_claim(bdi, bdc);
if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX)
bgp_reuselist_add(&bdc->no_reuse_list, bdi);
else
bgp_reuselist_add(&bdc->reuse_list[bdi->index],
bdi);
}
last_penalty = bdi->penalty;
/* 1. Set t-diff = t-now - t-updated. */
@ -322,8 +245,8 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
/* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) {
/* If decay rate isn't equal to 0, reinsert brn. */
if (bdi->penalty != last_penalty) {
bgp_reuse_list_delete(bdi);
if (bdi->penalty != last_penalty && bdi->index >= 0) {
bgp_reuse_list_delete(bdi, bdc);
bgp_reuse_list_add(bdi, bdc);
}
return BGP_DAMP_SUPPRESSED;
@ -334,9 +257,10 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
if (bdi->penalty >= bdc->suppress_value) {
bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED);
bdi->suppress_time = t_now;
bgp_no_reuse_list_delete(bdi);
BGP_DAMP_LIST_DEL(bdc, bdi);
bgp_reuse_list_add(bdi, bdc);
}
return BGP_DAMP_USED;
}
@ -346,10 +270,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
time_t t_now;
struct bgp_damp_info *bdi;
int status;
struct bgp_damp_config *bdc;
bdc = get_active_bdc_from_pi(path, afi, safi);
assert(bdc);
struct bgp_damp_config *bdc = &damp[afi][safi];
if (!path->extra || !((bdi = path->extra->damp_info)))
return BGP_DAMP_USED;
@ -367,8 +288,8 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
&& (bdi->penalty < bdc->reuse_limit)) {
bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED);
bgp_reuse_list_delete(bdi);
bgp_no_reuse_list_add(bdi, bdc);
bgp_reuse_list_delete(bdi, bdc);
BGP_DAMP_LIST_ADD(bdc, bdi);
bdi->suppress_time = 0;
status = BGP_DAMP_USED;
} else
@ -376,28 +297,36 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
if (bdi->penalty > bdc->reuse_limit / 2.0)
bdi->t_updated = t_now;
else {
bgp_damp_info_unclaim(bdi);
bgp_damp_info_free(bdi, 0);
}
else
bgp_damp_info_free(bdi, 0, afi, safi);
return status;
}
void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
safi_t safi)
{
assert(bdi);
struct bgp_path_info *path;
struct bgp_damp_config *bdc = &damp[afi][safi];
if (bdi->path == NULL) {
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
if (!bdi)
return;
}
bdi->path->extra->damp_info = NULL;
bgp_path_info_unset_flag(bdi->dest, bdi->path,
path = bdi->path;
path->extra->damp_info = NULL;
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
bgp_reuse_list_delete(bdi, bdc);
else
BGP_DAMP_LIST_DEL(bdc, bdi);
bgp_path_info_unset_flag(bdi->dest, path,
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
bgp_path_info_delete(bdi->dest, bdi->path);
bgp_path_info_delete(bdi->dest, path);
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
}
static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup,
@ -440,7 +369,8 @@ static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup,
bdc->reuse_list =
XCALLOC(MTYPE_BGP_DAMP_ARRAY,
bdc->reuse_list_size * sizeof(struct reuselist));
bdc->reuse_list_size * sizeof(struct bgp_reuse_node *));
/* Reuse-array computations */
bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
sizeof(int) * bdc->reuse_index_size);
@ -467,7 +397,7 @@ static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup,
int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
unsigned int reuse, unsigned int suppress, time_t max)
{
struct bgp_damp_config *bdc = &bgp->damp[afi][safi];
struct bgp_damp_config *bdc = &damp[afi][safi];
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
if (bdc->half_life == half && bdc->reuse_limit == reuse
@ -479,8 +409,6 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
bdc->afi = afi;
bdc->safi = safi;
/* Register reuse timer. */
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
@ -489,35 +417,8 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
return 0;
}
/* Clean all the bgp_damp_info stored in reuse_list and no_reuse_list. */
void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
afi_t afi, safi_t safi)
static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
{
struct bgp_damp_info *bdi;
struct reuselist *list;
unsigned int i;
bdc->reuse_offset = 0;
for (i = 0; i < bdc->reuse_list_size; ++i) {
list = &bdc->reuse_list[i];
while ((bdi = SLIST_FIRST(list)) != NULL) {
if (bdi->lastrecord == BGP_RECORD_UPDATE) {
bgp_aggregate_increment(bgp, &bdi->dest->p,
bdi->path, bdi->afi,
bdi->safi);
bgp_process(bgp, bdi->dest, bdi->afi,
bdi->safi);
}
bgp_reuselist_del(list, bdi);
bgp_damp_info_free(bdi, 1);
}
}
while ((bdi = SLIST_FIRST(&bdc->no_reuse_list)) != NULL) {
bgp_reuselist_del(&bdc->no_reuse_list, bdi);
bgp_damp_info_free(bdi, 1);
}
/* Free decay array */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array);
bdc->decay_array_size = 0;
@ -526,78 +427,97 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
bdc->reuse_index_size = 0;
/* Free reuse list array. */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
bdc->reuse_list_size = 0;
THREAD_OFF(bdc->t_reuse);
}
/* Disable route flap dampening for a bgp instance.
*
* Please note that this function also gets used to free memory when deleting a
* bgp instance.
*/
/* Clean all the bgp_damp_info stored in reuse_list. */
void bgp_damp_info_clean(afi_t afi, safi_t safi)
{
unsigned int i;
struct bgp_damp_info *bdi, *next;
struct bgp_damp_config *bdc = &damp[afi][safi];
bdc->reuse_offset = 0;
for (i = 0; i < bdc->reuse_list_size; i++) {
if (!bdc->reuse_list[i])
continue;
for (bdi = bdc->reuse_list[i]; bdi; bdi = next) {
next = bdi->next;
bgp_damp_info_free(bdi, 1, afi, safi);
}
bdc->reuse_list[i] = NULL;
}
for (bdi = bdc->no_reuse_list; bdi; bdi = next) {
next = bdi->next;
bgp_damp_info_free(bdi, 1, afi, safi);
}
bdc->no_reuse_list = NULL;
}
int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_damp_config *bdc;
bdc = &bgp->damp[afi][safi];
if (!bdc)
return 0;
struct bgp_damp_config *bdc = &damp[afi][safi];
/* If it wasn't enabled, there's nothing to do. */
if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
return 0;
/* Cancel reuse event. */
thread_cancel(&bdc->t_reuse);
thread_cancel(&(bdc->t_reuse));
/* Clean BGP dampening information. */
bgp_damp_info_clean(bgp, bdc, afi, safi);
bgp_damp_info_clean(afi, safi);
/* Clear configuration */
bgp_damp_config_clean(bdc);
UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
return 0;
}
void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi)
{
struct bgp_damp_config *bdc;
bdc = &bgp->damp[afi][safi];
if (bdc->half_life == DEFAULT_HALF_LIFE * 60
&& bdc->reuse_limit == DEFAULT_REUSE
&& bdc->suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4)
if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60
&& damp[afi][safi].reuse_limit == DEFAULT_REUSE
&& damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
&& damp[afi][safi].max_suppress_time
== damp[afi][safi].half_life * 4)
vty_out(vty, " bgp dampening\n");
else if (bdc->half_life != DEFAULT_HALF_LIFE * 60
&& bdc->reuse_limit == DEFAULT_REUSE
&& bdc->suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4)
vty_out(vty, " bgp dampening %lld\n", bdc->half_life / 60LL);
else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60
&& damp[afi][safi].reuse_limit == DEFAULT_REUSE
&& damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
&& damp[afi][safi].max_suppress_time
== damp[afi][safi].half_life * 4)
vty_out(vty, " bgp dampening %lld\n",
damp[afi][safi].half_life / 60LL);
else
vty_out(vty, " bgp dampening %lld %d %d %lld\n",
bdc->half_life / 60LL, bdc->reuse_limit,
bdc->suppress_value, bdc->max_suppress_time / 60LL);
damp[afi][safi].half_life / 60LL,
damp[afi][safi].reuse_limit,
damp[afi][safi].suppress_value,
damp[afi][safi].max_suppress_time / 60LL);
}
static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc,
unsigned int penalty, char *buf,
size_t len, bool use_json,
json_object *json)
static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
size_t len, afi_t afi, safi_t safi,
bool use_json, json_object *json)
{
time_t reuse_time = 0;
struct tm tm;
int time_store = 0;
if (penalty > bdc->reuse_limit) {
if (penalty > damp[afi][safi].reuse_limit) {
reuse_time = (int)(DELTA_T
* ((log((double)bdc->reuse_limit / penalty))
/ (log(bdc->decay_array[1]))));
* ((log((double)damp[afi][safi].reuse_limit
/ penalty))
/ (log(damp[afi][safi].decay_array[1]))));
if (reuse_time > bdc->max_suppress_time)
reuse_time = bdc->max_suppress_time;
if (reuse_time > damp[afi][safi].max_suppress_time)
reuse_time = damp[afi][safi].max_suppress_time;
gmtime_r(&reuse_time, &tm);
} else
@ -649,15 +569,14 @@ static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc,
return buf;
}
void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
struct bgp_path_info *path, afi_t afi, safi_t safi,
json_object *json_path)
void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
safi_t safi, json_object *json_path)
{
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
char timebuf[BGP_UPTIME_LEN];
int penalty;
struct bgp_damp_config *bdc = &bgp->damp[afi][safi];
struct bgp_damp_config *bdc = &damp[afi][safi];
if (!path->extra)
return;
@ -683,8 +602,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
bgp_get_reuse_time(bdc, penalty, timebuf,
BGP_UPTIME_LEN, 1, json_path);
bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN,
afi, safi, 1, json_path);
} else {
vty_out(vty,
" Dampinfo: penalty %d, flapped %d times in %s",
@ -695,15 +614,14 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, ", reuse in %s",
bgp_get_reuse_time(bdc, penalty, timebuf,
BGP_UPTIME_LEN, 0,
bgp_get_reuse_time(penalty, timebuf,
BGP_UPTIME_LEN, afi, safi, 0,
json_path));
vty_out(vty, "\n");
}
}
const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi,
safi_t safi, bool use_json,
@ -712,11 +630,7 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
int penalty;
struct bgp_damp_config *bdc;
bdc = get_active_bdc_from_pi(path, afi, safi);
if (!bdc)
return NULL;
struct bgp_damp_config *bdc = &damp[afi][safi];
if (!path->extra)
return NULL;
@ -726,7 +640,7 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
/* If dampening is not enabled or there is no dampening information,
return immediately. */
if (!bdi)
if (!bdc || !bdi)
return NULL;
/* Calculate new penalty. */
@ -734,23 +648,24 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
return bgp_get_reuse_time(bdc, penalty, timebuf, len, use_json, json);
return bgp_get_reuse_time(penalty, timebuf, len, afi, safi, use_json,
json);
}
static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty,
afi_t afi, safi_t safi)
{
struct bgp_damp_config *bdc;
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
bdc = &bgp->damp[afi][safi];
vty_out(vty, "Half-life time: %lld min\n",
(long long)bdc->half_life / 60);
vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit);
vty_out(vty, "Suppress penalty: %d\n", bdc->suppress_value);
(long long)damp[afi][safi].half_life / 60);
vty_out(vty, "Reuse penalty: %d\n",
damp[afi][safi].reuse_limit);
vty_out(vty, "Suppress penalty: %d\n",
damp[afi][safi].suppress_value);
vty_out(vty, "Max suppress time: %lld min\n",
(long long)bdc->max_suppress_time / 60);
vty_out(vty, "Max suppress penalty: %u\n", bdc->ceiling);
(long long)damp[afi][safi].max_suppress_time / 60);
vty_out(vty, "Max suppress penalty: %u\n",
damp[afi][safi].ceiling);
vty_out(vty, "\n");
} else
vty_out(vty, "dampening not enabled for %s\n",
@ -763,8 +678,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
uint16_t show_flags)
{
struct bgp *bgp;
bgp = bgp_get_default();
if (bgp == NULL) {
vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING;
@ -803,132 +718,3 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
}
return CMD_SUCCESS;
}
void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi,
time_t half, unsigned int reuse,
unsigned int suppress, time_t max)
{
struct bgp_damp_config *bdc;
if (!peer)
return;
bdc = &peer->damp[afi][safi];
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) {
if (bdc->half_life == half && bdc->reuse_limit == reuse
&& bdc->suppress_value == suppress
&& bdc->max_suppress_time == max)
return;
bgp_peer_damp_disable(peer, afi, safi);
}
SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING);
bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
bdc->afi = afi;
bdc->safi = safi;
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
&bdc->t_reuse);
}
/* Disable route flap dampening for a peer.
*
* Please note that this function also gets used to free memory when deleting a
* peer or peer group.
*/
void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_damp_config *bdc;
if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING))
return;
bdc = &peer->damp[afi][safi];
if (!bdc)
return;
bgp_damp_info_clean(peer->bgp, bdc, afi, safi);
UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING);
}
void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer, afi_t afi,
safi_t safi)
{
struct bgp_damp_config *bdc;
bdc = &peer->damp[afi][safi];
if (bdc->half_life == DEFAULT_HALF_LIFE * 60
&& bdc->reuse_limit == DEFAULT_REUSE
&& bdc->suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4)
vty_out(vty, " neighbor %s dampening\n", peer->host);
else if (bdc->half_life != DEFAULT_HALF_LIFE * 60
&& bdc->reuse_limit == DEFAULT_REUSE
&& bdc->suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4)
vty_out(vty, " neighbor %s dampening %lld\n", peer->host,
bdc->half_life / 60LL);
else
vty_out(vty, " neighbor %s dampening %lld %d %d %lld\n",
peer->host, bdc->half_life / 60LL, bdc->reuse_limit,
bdc->suppress_value, bdc->max_suppress_time / 60LL);
}
static void bgp_print_peer_dampening_parameters(struct vty *vty,
struct peer *peer, afi_t afi,
safi_t safi, bool use_json,
json_object *json)
{
struct bgp_damp_config *bdc;
if (!peer)
return;
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING)) {
bdc = &peer->damp[afi][safi];
if (!bdc)
return;
if (use_json) {
json_object_int_add(json, "halfLifeSecs",
bdc->half_life);
json_object_int_add(json, "reusePenalty",
bdc->reuse_limit);
json_object_int_add(json, "suppressPenalty",
bdc->suppress_value);
json_object_int_add(json, "maxSuppressTimeSecs",
bdc->max_suppress_time);
json_object_int_add(json, "maxSuppressPenalty",
bdc->ceiling);
} else {
vty_out(vty, "Half-life time: %lld min\n",
(long long)bdc->half_life / 60);
vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit);
vty_out(vty, "Suppress penalty: %d\n",
bdc->suppress_value);
vty_out(vty, "Max suppress time: %lld min\n",
(long long)bdc->max_suppress_time / 60);
vty_out(vty, "Max suppress penalty: %u\n",
bdc->ceiling);
vty_out(vty, "\n");
}
} else if (!use_json)
vty_out(vty, "neighbor dampening not enabled for %s\n",
get_afi_safi_str(afi, safi, false));
}
void bgp_show_peer_dampening_parameters(struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi, bool use_json)
{
json_object *json;
if (use_json) {
json = json_object_new_object();
json_object_string_add(json, "addressFamily",
get_afi_safi_str(afi, safi, false));
bgp_print_peer_dampening_parameters(vty, peer, afi, safi, true,
json);
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
} else {
vty_out(vty, "\nFor address family: %s\n",
get_afi_safi_str(afi, safi, false));
bgp_print_peer_dampening_parameters(vty, peer, afi, safi, false,
NULL);
}
}

View File

@ -25,6 +25,11 @@
/* Structure maintained on a per-route basis. */
struct bgp_damp_info {
/* Doubly linked list. This information must be linked to
reuse_list or no_reuse_list. */
struct bgp_damp_info *next;
struct bgp_damp_info *prev;
/* Figure-of-merit. */
unsigned int penalty;
@ -40,9 +45,6 @@ struct bgp_damp_info {
/* Time of route start to be suppressed. */
time_t suppress_time;
/* Back reference to associated dampening configuration. */
struct bgp_damp_config *config;
/* Back reference to bgp_path_info. */
struct bgp_path_info *path;
@ -51,8 +53,6 @@ struct bgp_damp_info {
/* Current index in the reuse_list. */
int index;
#define BGP_DAMP_NO_REUSE_LIST_INDEX \
(-1) /* index for elements on no_reuse_list */
/* Last time message type. */
uint8_t lastrecord;
@ -61,12 +61,8 @@ struct bgp_damp_info {
afi_t afi;
safi_t safi;
SLIST_ENTRY(bgp_damp_info) entry;
};
SLIST_HEAD(reuselist, bgp_damp_info);
/* Specified parameter set configuration. */
struct bgp_damp_config {
/* Value over which routes suppressed. */
@ -104,11 +100,11 @@ struct bgp_damp_config {
int *reuse_index;
/* Reuse list array per-set based. */
struct reuselist *reuse_list;
unsigned int reuse_offset;
struct bgp_damp_info **reuse_list;
int reuse_offset;
/* All dampening information which is not on reuse list. */
struct reuselist no_reuse_list;
struct bgp_damp_info *no_reuse_list;
/* Reuse timer thread per-set base. */
struct thread *t_reuse;
@ -136,8 +132,6 @@ struct bgp_damp_config {
#define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024
extern struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi,
afi_t afi, safi_t safi);
extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t);
extern int bgp_damp_disable(struct bgp *, afi_t, safi_t);
@ -145,16 +139,13 @@ extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
afi_t afi, safi_t safi, int attr_change);
extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
afi_t afi, safi_t saff);
extern void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw);
extern void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
afi_t afi, safi_t safi);
extern void bgp_damp_config_clean(struct bgp_damp_config *bdc);
extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw,
afi_t afi, safi_t safi);
extern void bgp_damp_info_clean(afi_t afi, safi_t safi);
extern int bgp_damp_decay(time_t, int, struct bgp_damp_config *damp);
extern void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi);
extern void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
struct bgp_path_info *path, afi_t afi,
safi_t safi, json_object *json_path);
extern void bgp_config_write_damp(struct vty *, afi_t afi, safi_t safi);
extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
afi_t afi, safi_t safi, json_object *json_path);
extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi,
@ -162,14 +153,5 @@ extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
json_object *json);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t,
uint16_t);
extern void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi,
time_t half, unsigned int reuse,
unsigned int suppress, time_t max);
extern void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi);
extern void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer,
afi_t afi, safi_t safi);
extern void bgp_show_peer_dampening_parameters(struct vty *vty,
struct peer *peer, afi_t afi,
safi_t safi, bool use_json);
#endif /* _QUAGGA_BGP_DAMP_H */

View File

@ -100,7 +100,6 @@ DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface");
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface");
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info");
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array");
DEFINE_MTYPE(BGPD, BGP_DAMP_REUSELIST, "BGP Dampening reuse list");
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp");
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate");
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address");

View File

@ -96,7 +96,6 @@ DECLARE_MTYPE(PEER_UPDATE_SOURCE);
DECLARE_MTYPE(PEER_CONF_IF);
DECLARE_MTYPE(BGP_DAMP_INFO);
DECLARE_MTYPE(BGP_DAMP_ARRAY);
DECLARE_MTYPE(BGP_DAMP_REUSELIST);
DECLARE_MTYPE(BGP_REGEXP);
DECLARE_MTYPE(BGP_AGGREGATE);
DECLARE_MTYPE(BGP_ADDR);

View File

@ -218,11 +218,11 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
return;
e = *extra;
if (e->damp_info)
bgp_damp_info_free(e->damp_info, 0);
e->damp_info = NULL;
bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
e->damp_info->safi);
e->damp_info = NULL;
if (e->parent) {
struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
@ -3391,16 +3391,14 @@ static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
/* apply dampening, if result is suppressed, we'll be retaining
* the bgp_path_info in the RIB for historical reference.
*/
if (peer->sort == BGP_PEER_EBGP) {
if (get_active_bdc_from_pi(pi, afi, safi)) {
if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
== BGP_DAMP_SUPPRESSED) {
bgp_aggregate_decrement(peer->bgp, p, pi, afi,
safi);
return;
}
if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP)
if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
== BGP_DAMP_SUPPRESSED) {
bgp_aggregate_decrement(peer->bgp, p, pi, afi,
safi);
return;
}
}
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
@ -3849,7 +3847,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|| memcmp(&(bgp_path_info_extra_get(pi))->label, label,
num_labels * sizeof(mpls_label_t))
== 0)) {
if (get_active_bdc_from_pi(pi, afi, safi)
if (CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP
&& CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
if (bgp_debug_update(peer, p, NULL, 1)) {
@ -3951,11 +3950,11 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
/* Update bgp route dampening information. */
if (get_active_bdc_from_pi(pi, afi, safi)
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP) {
/* This is implicit withdraw so we should update
* dampening information.
*/
dampening
information. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
bgp_damp_withdraw(pi, dest, afi, safi, 1);
}
@ -4078,7 +4077,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
#endif
/* Update bgp route dampening information. */
if (get_active_bdc_from_pi(pi, afi, safi)
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
&& peer->sort == BGP_PEER_EBGP) {
/* Now we do normal update dampening. */
ret = bgp_damp_update(pi, dest, afi, safi);
@ -10439,7 +10438,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
if (path->extra && path->extra->damp_info)
bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
bgp_damp_info_vty(vty, path, afi, safi, json_path);
/* Remote Label */
if (path->extra && bgp_is_valid_label(&path->extra->label[0])
@ -14647,7 +14646,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
pi_temp = pi->next;
bgp_damp_info_free(
pi->extra->damp_info,
1);
1, afi, safi);
pi = pi_temp;
} else
pi = pi->next;
@ -14667,24 +14666,9 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
while (pi) {
if (pi->extra && pi->extra->damp_info) {
pi_temp = pi->next;
struct bgp_damp_info *bdi =
pi->extra->damp_info;
if (bdi->lastrecord
== BGP_RECORD_UPDATE) {
bgp_aggregate_increment(
bgp,
&bdi->dest->p,
bdi->path,
bdi->afi,
bdi->safi);
bgp_process(bgp,
bdi->dest,
bdi->afi,
bdi->safi);
}
bgp_damp_info_free(
pi->extra->damp_info,
1);
1, afi, safi);
pi = pi_temp;
} else
pi = pi->next;
@ -14706,9 +14690,7 @@ DEFUN (clear_ip_bgp_dampening,
BGP_STR
"Clear route flap dampening information\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
SAFI_UNICAST);
bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
return CMD_SUCCESS;
}

View File

@ -8046,93 +8046,6 @@ DEFPY(
return CMD_SUCCESS;
}
DEFPY(neighbor_damp,
neighbor_damp_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [(1-45)$half [(1-20000)$reuse (1-20000)$suppress (1-255)$max]]",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Enable neighbor route-flap dampening\n"
"Half-life time for the penalty\n"
"Value to start reusing a route\n"
"Value to start suppressing a route\n"
"Maximum duration to suppress a stable route\n")
{
struct peer *peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
if (!half)
half = DEFAULT_HALF_LIFE;
if (!reuse) {
reuse = DEFAULT_REUSE;
suppress = DEFAULT_SUPPRESS;
max = half * 4;
}
if (suppress < reuse) {
vty_out(vty,
"Suppress value cannot be less than reuse value\n");
return CMD_WARNING_CONFIG_FAILED;
}
bgp_peer_damp_enable(peer, bgp_node_afi(vty), bgp_node_safi(vty),
half * 60, reuse, suppress, max * 60);
return CMD_SUCCESS;
}
DEFPY(no_neighbor_damp,
no_neighbor_damp_cmd,
"no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [HALF [REUSE SUPPRESS MAX]]",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Enable neighbor route-flap dampening\n"
"Half-life time for the penalty\n"
"Value to start reusing a route\n"
"Value to start suppressing a route\n"
"Maximum duration to suppress a stable route\n")
{
struct peer *peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
bgp_peer_damp_disable(peer, bgp_node_afi(vty), bgp_node_safi(vty));
return CMD_SUCCESS;
}
DEFPY (show_ip_bgp_neighbor_damp_param,
show_ip_bgp_neighbor_damp_param_cmd,
"show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD>$neighbor dampening parameters [json]$json",
SHOW_STR
IP_STR
BGP_STR
BGP_AFI_HELP_STR
"Address Family modifier\n"
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Neighbor route-flap dampening information\n"
"Display detail of configured dampening parameters\n"
JSON_STR)
{
bool use_json = false;
int idx = 0;
afi_t afi = AFI_IP;
safi_t safi = SAFI_UNICAST;
struct peer *peer;
if (argv_find(argv, argc, "ip", &idx))
afi = AFI_IP;
if (argv_find(argv, argc, "ipv4", &idx))
afi = AFI_IP;
if (argv_find(argv, argc, "ipv6", &idx))
afi = AFI_IP6;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING;
if (json)
use_json = true;
bgp_show_peer_dampening_parameters(vty, peer, afi, safi, use_json);
return CMD_SUCCESS;
}
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
struct ecommunity **list, bool is_rt6)
{
@ -16794,9 +16707,6 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
: "");
}
}
if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING))
bgp_config_write_peer_damp(vty, peer, afi, safi);
}
/* Address family based peer configuration display. */
@ -16849,7 +16759,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
/* BGP flag dampening. */
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
bgp_config_write_damp(vty, bgp, afi, safi);
bgp_config_write_damp(vty, afi, safi);
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
@ -18658,23 +18568,6 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd);
/* "neighbor dampening" commands. */
install_element(BGP_NODE, &neighbor_damp_cmd);
install_element(BGP_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV4_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV4_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV4M_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV4M_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV4L_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV4L_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV6_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV6_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV6M_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV6M_NODE, &no_neighbor_damp_cmd);
install_element(BGP_IPV6L_NODE, &neighbor_damp_cmd);
install_element(BGP_IPV6L_NODE, &no_neighbor_damp_cmd);
install_element(VIEW_NODE, &show_ip_bgp_neighbor_damp_param_cmd);
/* address-family commands. */
install_element(BGP_NODE, &address_family_ipv4_safi_cmd);
install_element(BGP_NODE, &address_family_ipv6_safi_cmd);

View File

@ -2412,14 +2412,6 @@ int peer_delete(struct peer *peer)
if (peer->bfd_config)
bgp_peer_remove_bfd_config(peer);
/* Delete peer route flap dampening configuration. This needs to happen
* before removing the peer from peer groups.
*/
FOREACH_AFI_SAFI (afi, safi)
if (peer_af_flag_check(peer, afi, safi,
PEER_FLAG_CONFIG_DAMPENING))
bgp_peer_damp_disable(peer, afi, safi);
/* If this peer belongs to peer group, clear up the
relationship. */
if (peer->group) {
@ -3603,11 +3595,6 @@ int bgp_delete(struct bgp *bgp)
BGP_TIMER_OFF(gr_info->t_route_select);
}
/* Delete route flap dampening configuration */
FOREACH_AFI_SAFI (afi, safi) {
bgp_damp_disable(bgp, afi, safi);
}
if (BGP_DEBUG(zebra, ZEBRA)) {
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
zlog_debug("Deleting Default VRF");

View File

@ -44,7 +44,6 @@
#include "bgp_labelpool.h"
#include "bgp_addpath_types.h"
#include "bgp_nexthop.h"
#include "bgp_damp.h"
#include "bgp_io.h"
#include "lib/bfd.h"
@ -752,9 +751,6 @@ struct bgp {
uint32_t condition_filter_count;
struct thread *t_condition_check;
/* BGP route flap dampening configuration */
struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
/* BGP VPN SRv6 backend */
bool srv6_enabled;
char srv6_locator_name[SRV6_LOCNAME_SIZE];
@ -1314,9 +1310,6 @@ struct peer {
/* Last update packet sent time */
time_t pkt_stime[AFI_MAX][SAFI_MAX];
/* Peer / peer group route flap dampening configuration */
struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
/* Peer Per AF flags */
/*
* Please consult the comments for *flags_override*, *flags_invert* and
@ -1354,8 +1347,6 @@ struct peer {
#define PEER_FLAG_SEND_LARGE_COMMUNITY (1U << 26) /* Send large Communities */
#define PEER_FLAG_MAX_PREFIX_OUT (1U << 27) /* outgoing maximum prefix */
#define PEER_FLAG_MAX_PREFIX_FORCE (1U << 28) /* maximum-prefix <num> force */
#define PEER_FLAG_CONFIG_DAMPENING (1U << 29) /* route flap dampening */
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];

View File

@ -515,54 +515,28 @@ Disable checking if nexthop is connected on EBGP sessions
Route Flap Dampening
--------------------
.. clicmd:: bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
.. clicmd:: bgp dampening (1-45) (1-20000) (1-20000) (1-255)
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes of a BGP instance.
.. clicmd:: neighbor PEER dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes learned from a BGP peer.
.. clicmd:: neighbor GROUP dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes learned from peers of a peer
group.
This command enables BGP route-flap dampening and specifies dampening parameters.
half-life
Half-life time for the penalty in minutes (default value: 15).
Half-life time for the penalty
reuse-threshold
Value to start reusing a route (default value: 750).
Value to start reusing a route
suppress-threshold
Value to start suppressing a route (default value: 2000).
Value to start suppressing a route
max-suppress
Maximum duration to suppress a stable route in minutes (default value:
60).
Maximum duration to suppress a stable route
The route-flap damping algorithm is compatible with :rfc:`2439`. The use of
these commands is not recommended nowadays.
this command is not recommended nowadays.
At the moment, route-flap dampening is not working per VRF and is working only
for IPv4 unicast and multicast.
With different parameter sets configurable for BGP instances, peer groups and
peers, the active dampening profile for a route is chosen on the fly,
allowing for various changes in configuration (i.e. peer group memberships)
during runtime. The parameter sets are taking precedence in the following
order:
1. Peer
2. Peer group
3. BGP instance
The negating commands do not allow to exclude a peer/peer group from a peer
group/BGP instances configuration.
.. seealso::
https://www.ripe.net/publications/docs/ripe-378

View File

@ -1,53 +0,0 @@
[exabgp.api]
encoder = text
highres = false
respawn = false
socket = ''
[exabgp.bgp]
openwait = 60
[exabgp.cache]
attributes = true
nexthops = true
[exabgp.daemon]
daemonize = true
pid = '/var/run/exabgp/exabgp.pid'
user = 'exabgp'
[exabgp.log]
all = false
configuration = true
daemon = true
destination = '/var/log/exabgp.log'
enable = true
level = INFO
message = false
network = true
packets = false
parser = false
processes = true
reactor = true
rib = false
routes = false
short = false
timers = false
[exabgp.pdb]
enable = false
[exabgp.profile]
enable = false
file = ''
[exabgp.reactor]
speed = 1.0
[exabgp.tcp]
acl = false
bind = ''
delay = 0
once = false
port = 179

View File

@ -1,19 +0,0 @@
#!/usr/bin/env python
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
if len(sys.argv) != 2:
sys.exit(1)
fifo = sys.argv[1]
while True:
pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
sys.stdout.write("{}\n".format(line))
sys.stdout.flush()
pipe.close()
sys.exit(0)

View File

@ -1,12 +0,0 @@
group exabgp {
process announce-routes {
run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer1.in";
encoder text;
}
neighbor 192.168.101.1 {
router-id 192.168.101.3;
local-address 192.168.101.3;
local-as 65403;
peer-as 65000;
}
}

View File

@ -1,19 +0,0 @@
#!/usr/bin/env python
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
if len(sys.argv) != 2:
sys.exit(1)
fifo = sys.argv[1]
while True:
pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
sys.stdout.write("{}\n".format(line))
sys.stdout.flush()
pipe.close()
sys.exit(0)

View File

@ -1,12 +0,0 @@
group exabgp {
process announce-routes {
run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer2.in";
encoder text;
}
neighbor 192.168.101.1 {
router-id 192.168.101.4;
local-address 192.168.101.4;
local-as 65404;
peer-as 65000;
}
}

View File

@ -1,19 +0,0 @@
#!/usr/bin/env python
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
if len(sys.argv) != 2:
sys.exit(1)
fifo = sys.argv[1]
while True:
pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
sys.stdout.write("{}\n".format(line))
sys.stdout.flush()
pipe.close()
sys.exit(0)

View File

@ -1,12 +0,0 @@
group exabgp {
process announce-routes {
run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer3.in";
encoder text;
}
neighbor 192.168.101.1 {
router-id 192.168.101.5;
local-address 192.168.101.5;
local-as 65405;
peer-as 65000;
}
}

View File

@ -1,19 +0,0 @@
#!/usr/bin/env python
"Helper script to read api commands from a pipe and feed them to ExaBGP"
import sys
if len(sys.argv) != 2:
sys.exit(1)
fifo = sys.argv[1]
while True:
pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
sys.stdout.write("{}\n".format(line))
sys.stdout.flush()
pipe.close()
sys.exit(0)

View File

@ -1,12 +0,0 @@
group exabgp {
process announce-routes {
run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer4.in";
encoder text;
}
neighbor 192.168.101.1 {
router-id 192.168.101.6;
local-address 192.168.101.6;
local-as 65406;
peer-as 65000;
}
}

View File

@ -1,21 +0,0 @@
{
"localAS":65000,
"routes":{
"192.168.31.0/24": [ { "valid":true, "network":"192.168.31.0\/24", "peerId":"192.168.101.3" } ],
"192.168.32.0/24": [ { "valid":true, "network":"192.168.32.0\/24", "peerId":"192.168.101.3" } ],
"192.168.33.0/24": [ { "valid":true, "network":"192.168.33.0\/24", "peerId":"192.168.101.3" } ],
"192.168.34.0/24": [ { "valid":true, "network":"192.168.34.0\/24", "peerId":"192.168.101.3" } ],
"192.168.41.0/24": [ { "valid":true, "network":"192.168.41.0\/24", "peerId":"192.168.101.4" } ],
"192.168.42.0/24": [ { "valid":true, "network":"192.168.42.0\/24", "peerId":"192.168.101.4" } ],
"192.168.43.0/24": [ { "valid":true, "network":"192.168.43.0\/24", "peerId":"192.168.101.4" } ],
"192.168.44.0/24": [ { "valid":true, "network":"192.168.44.0\/24", "peerId":"192.168.101.4" } ],
"192.168.51.0/24": [ { "valid":true, "network":"192.168.51.0\/24", "peerId":"192.168.101.5" } ],
"192.168.52.0/24": [ { "valid":true, "network":"192.168.52.0\/24", "peerId":"192.168.101.5" } ],
"192.168.53.0/24": [ { "valid":true, "network":"192.168.53.0\/24", "peerId":"192.168.101.5" } ],
"192.168.54.0/24": [ { "valid":true, "network":"192.168.54.0\/24", "peerId":"192.168.101.5" } ],
"192.168.61.0/24": [ { "valid":true, "network":"192.168.61.0\/24", "peerId":"192.168.101.6" } ],
"192.168.62.0/24": [ { "valid":true, "network":"192.168.62.0\/24", "peerId":"192.168.101.6" } ],
"192.168.63.0/24": [ { "valid":true, "network":"192.168.63.0\/24", "peerId":"192.168.101.6" } ],
"192.168.64.0/24": [ { "valid":true, "network":"192.168.64.0\/24", "peerId":"192.168.101.6" } ]
}
}

View File

@ -1,10 +0,0 @@
{
"ipv4Unicast":{
"peers":{
"192.168.101.3":{"remoteAs":65403, "state":"Established"},
"192.168.101.4":{"remoteAs":65404, "state":"Established"},
"192.168.101.5":{"remoteAs":65405, "state":"Established"},
"192.168.101.6":{"remoteAs":65406, "state":"Established"}
}
}
}

View File

@ -1,21 +0,0 @@
{
"localAS":65000,
"routes":{
"192.168.31.0/24": [ { "network":"192.168.31.0\/24", "peerId":"192.168.0.1" } ],
"192.168.32.0/24": [ { "network":"192.168.32.0\/24", "peerId":"192.168.0.1" } ],
"192.168.33.0/24": [ { "network":"192.168.33.0\/24", "peerId":"192.168.0.1" } ],
"192.168.34.0/24": [ { "network":"192.168.34.0\/24", "peerId":"192.168.0.1" } ],
"192.168.41.0/24": [ { "network":"192.168.41.0\/24", "peerId":"192.168.0.1" } ],
"192.168.42.0/24": [ { "network":"192.168.42.0\/24", "peerId":"192.168.0.1" } ],
"192.168.43.0/24": [ { "network":"192.168.43.0\/24", "peerId":"192.168.0.1" } ],
"192.168.44.0/24": [ { "network":"192.168.44.0\/24", "peerId":"192.168.0.1" } ],
"192.168.51.0/24": [ { "network":"192.168.51.0\/24", "peerId":"192.168.0.1" } ],
"192.168.52.0/24": [ { "network":"192.168.52.0\/24", "peerId":"192.168.0.1" } ],
"192.168.53.0/24": [ { "network":"192.168.53.0\/24", "peerId":"192.168.0.1" } ],
"192.168.54.0/24": [ { "network":"192.168.54.0\/24", "peerId":"192.168.0.1" } ],
"192.168.61.0/24": [ { "network":"192.168.61.0\/24", "peerId":"192.168.0.1" } ],
"192.168.62.0/24": [ { "network":"192.168.62.0\/24", "peerId":"192.168.0.1" } ],
"192.168.63.0/24": [ { "network":"192.168.63.0\/24", "peerId":"192.168.0.1" } ],
"192.168.64.0/24": [ { "network":"192.168.64.0\/24", "peerId":"192.168.0.1" } ]
}
}

View File

@ -1,18 +0,0 @@
{
"192.168.31.0/24": null,
"192.168.32.0/24": null,
"192.168.33.0/24": null,
"192.168.34.0/24": null,
"192.168.41.0/24": null,
"192.168.42.0/24": null,
"192.168.43.0/24": null,
"192.168.44.0/24": null,
"192.168.51.0/24": null,
"192.168.52.0/24": null,
"192.168.53.0/24": null,
"192.168.54.0/24": null,
"192.168.61.0/24": null,
"192.168.62.0/24": null,
"192.168.63.0/24": null,
"192.168.64.0/24": null
}

View File

@ -33,7 +33,6 @@ import sys
import pytest
import re
import time
from time import sleep
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@ -67,14 +66,6 @@ class BGPFeaturesTopo1(Topo):
for rtrNum in range(1, 6):
tgen.add_router("r{}".format(rtrNum))
# create ExaBGP peers
for peer_num in range(1, 5):
tgen.add_exabgp_peer(
"peer{}".format(peer_num),
ip="192.168.101.{}".format(peer_num + 2),
defaultRoute="via 192.168.101.1",
)
# Setup Switches and connections
for swNum in range(1, 11):
tgen.add_switch("sw{}".format(swNum))
@ -100,12 +91,6 @@ class BGPFeaturesTopo1(Topo):
tgen.gears["r2"].add_link(tgen.gears["sw5"])
tgen.gears["r5"].add_link(tgen.gears["sw5"])
# Add ExaBGP peers to sw4
tgen.gears["peer1"].add_link(tgen.gears["sw4"])
tgen.gears["peer2"].add_link(tgen.gears["sw4"])
tgen.gears["peer3"].add_link(tgen.gears["sw4"])
tgen.gears["peer4"].add_link(tgen.gears["sw4"])
#####################################################
#
@ -1110,662 +1095,6 @@ def test_bgp_delayopen_dual():
# end test_bgp_delayopen_dual
def test_bgp_dampening_setup():
"BGP route-flap dampening test setup"
# This test starts four ExaBGP peers, adds them as neighbors to the
# configuration of router r1 and checks if connections get established.
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting BGP route-flap dampening test setup")
# Start ExaBGP peers connected to r1 via switch 4
logger.info("Starting ExaBGP peers")
for peer_num in range(1, 5):
logger.info("Creating named pipe for ExaBGP peer peer{}".format(peer_num))
fifo_in = "/var/run/exabgp_peer{}.in".format(peer_num)
if os.path.exists(fifo_in):
os.remove(fifo_in)
os.mkfifo(fifo_in, 0o777)
logger.info("Starting ExaBGP on peer peer{}".format(peer_num))
peer = tgen.gears["peer{}".format(peer_num)]
peer_dir = os.path.join(CWD, "peer{}".format(peer_num))
env_file = os.path.join(CWD, "exabgp.env")
peer.start(peer_dir, env_file)
# Add ExaBGP peers to configuration of router r2
logger.info("Adding ExaBGP peers as neighbors to configuration of router r2")
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.3 remote-as 65403"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 route-map testmap-in"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 route-map testmap-out"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.4 remote-as 65404"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.4 route-map testmap-in"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.4 route-map testmap-out"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.5 remote-as 65405"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 route-map testmap-in"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 route-map testmap-out"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.6 remote-as 65406"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.6 route-map testmap-in"'
)
tgen.net["r1"].cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.6 route-map testmap-out"'
)
# Check if exabgp peers are up and running
logger.info("Checking for established connections to ExaBGP peers on router r1")
router = tgen.gears["r1"]
reffile = os.path.join(CWD, "r1/bgp_damp_setup.json")
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, router, "show ip bgp summary json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = (
"BGP session on r1 did not establish connections with one ore more ExaBGP peers"
)
assert res is None, assertmsg
# end test_bgp_dampening_setup
def test_bgp_dampening_route_announce():
"Test of BGP route-flap dampening route announcement"
# This test checks if the four ExaBGP peers can announce routes to router
# r1 and if these routes get forwarded to router r2.
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting test of BGP route-flap dampening route announcement")
# Announce routes on exabgp peers to r2
logger.info("Announcing routes on ExaBGP peers to r1")
for prefix_iter in range(1, 5):
for peer_num in range(1, 5):
pipe = open("/run/exabgp_peer{}.in".format(peer_num), "w")
with pipe:
pipe.write(
"announce route 192.168.{}{}.0/24 next-hop 192.168.101.{}\n".format(
(peer_num + 2), prefix_iter, (peer_num + 2)
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Check if routes announced by ExaBGP peers are present in RIB of router r1
logger.info(
"Checking if routes announced by ExaBGP peers are present in RIB of router r1"
)
router = tgen.gears["r1"]
reffile = os.path.join(CWD, "r1/bgp_damp_announced.json")
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, router, "show ip bgp json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = (
"BGP session on router r1 did not receive routes announced by ExaBGP peers"
)
assert res is None, assertmsg
# Check if routes announced by ExaBGP peers to router r1 have been forwarded
# and are now present in RIB of router r2
logger.info(
"Checking if forwarded routes announced by ExaBGP peers are present in RIB of router r2"
)
router = tgen.gears["r2"]
reffile = os.path.join(CWD, "r2/bgp_damp_announced.json")
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, router, "show ip bgp json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = "BGP session on router r2 did not receive routes announced by ExaBGP peers forwarded by router r1"
assert res is None, assertmsg
# end test_bgp_dampening_route_announce
def test_bgp_dampening_disabled():
"Test of BGP route-flapping with dampening disabled"
# This test verifies that flapped routes do not get withdrawn from the RIB
# of router r1 if dampening is disabled.
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting test of BGP route-flapping with dampening disabled")
# Flapping routes on ExaBGP peer peer1
logger.info(
"Flapping routes on ExaBGP peer peer1 with route-flap dampening disabled"
)
for _ in range(1, 5):
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer1.in", "w")
with pipe:
pipe.write(
"withdraw route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
sleep(1) # Give the BGP session on router r1 time to process routes
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer1.in", "w")
with pipe:
pipe.write(
"announce route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Verify flapped routes are still present in RIB of router r1
logger.info(
"Verifying that the flapped routes are still present in RIB of router r1"
)
router = tgen.gears["r1"]
reffile = os.path.join(CWD, "r1/bgp_damp_announced.json")
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, router, "show ip bgp json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = "BGP session on router r1 removed flapped routes despite route-flap dampening being disabled"
assert res is None, assertmsg
# end test_bgp_dampening_disabled
def test_bgp_dampening_config():
"Test of BGP route-flap dampening configuration"
# This test adds peer-group group1 with peers peer1 and peer2 to the
# configuration of router r1, sets up dampening configurations with
# different profiles and verifies the configured dampening parameters.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting test of BGP route-flap dampening configuration")
# Add peer-group group1 with peers peer1 and peer2
logger.info(
"Creating peer-group group1 and adding ExaBGP peers peer1 and peer2 to it"
)
r_1.cmd('vtysh -c "conf t" -c "router bgp 65000" -c "neighbor group1 peer-group"')
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.3 peer-group group1"'
) # peer1
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.4 peer-group group1"'
) # peer2
# Enable different dampening profiles for peer1, peer3, group1 and global
# configuration
logger.info(
"Enabling different dampening profiles for peer1, peer3, group1 and global configuration"
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "bgp dampening 30 300 900 90"'
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor group1 dampening 20 200 600 60"'
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 dampening 10 100 300 30"'
) # peer1
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 dampening 10 100 300 30"'
) # peer3
# Verify route-flap dampening configuration
logger.info("Verifying route-flap dampening configuration on router r1")
vtyout = r_1.cmd('vtysh -c "show running-config"')
assertmsg = "BGP Session on r1 does not show enabled global route-flap dampening in running configuration"
assert re.search("bgp dampening 30 300 900 90", vtyout), assertmsg
assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer-group group1 in running configuration"
assert re.search("neighbor group1 dampening 20 200 600 60", vtyout), assertmsg
assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer peer1 in running configuration"
assert re.search(
"neighbor 192.168.101.3 dampening 10 100 300 30", vtyout
), assertmsg
assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer peer3 in running configuration"
assert re.search(
"neighbor 192.168.101.5 dampening 10 100 300 30", vtyout
), assertmsg
# end test_bgp_dampening_config
def test_bgp_dampening_profile_peer_over_group():
"Test of BGP route-flap dampening profile preferences: peer over group"
# This test verifies that the dampening profile of a peer takes precedence
# over the dampening profile of its peer-group by flapping the peers routes
# until dampened and comparing the reuse times to the one specified in the
# dampening configuration.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(
"Starting test of BGP route-flap dampening profile preferences: peer over group"
)
# Flapping routes on ExaBGP peer peer1
logger.info(
"Flapping routes on ExaBGP peer peer1 with route-flap dampening enabled"
)
for _ in range(1, 5):
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer1.in", "w")
with pipe:
pipe.write(
"withdraw route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
sleep(1) # Give the BGP session on router r1 time to process routes
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer1.in", "w")
with pipe:
pipe.write(
"announce route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Check damped paths on r1 for routes of peer1 witn peer profile
logger.info(
"Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer1"
)
sleep(5) # Wait 5 seconds for paths to show up in dampened-paths list
vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"')
routes = re.findall(r"\*d 192\.168\.3\d\.0\/24.*", vtyout)
assertmsg = (
"BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer1"
)
assert len(routes) == 4, assertmsg
assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer1"
for route in routes:
assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time
35 > int(route.split()[3].split(":")[1]) > 25
), assertmsg # minutes of reuse time
# end test_bgp_dampening_profile_peer_over_group
def test_bgp_dampening_profile_group_over_global():
"Test of BGP route-flap dampening profile preferences: group over global"
# This test verifies that the dampening profile of a peer-group takes
# precedence over the global dampening profile by flapping the routes of a
# peer-group member until dampened and comparing the reuse times to the one
# specified in the dampening configuration.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(
"Starting test of BGP route-flap dampening profile preferences: group over global"
)
# Flapping routes on ExaBGP peer peer2
logger.info(
"Flapping routes on ExaBGP peer peer2 with route-flap dampening enabled"
)
for _ in range(1, 5):
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer2.in", "w")
with pipe:
pipe.write(
"withdraw route 192.168.4{}.0/24 next-hop 192.168.101.4\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
sleep(1) # Give the BGP session on router r1 time to process routes
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer2.in", "w")
with pipe:
pipe.write(
"announce route 192.168.4{}.0/24 next-hop 192.168.101.4\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Check damped paths on r1 for routes of peer2 witn group profile
logger.info(
"Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer2"
)
sleep(5) # wait 5 seconds for paths to shop up in damp list
vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"')
routes = re.findall(r"\*d 192\.168\.4\d\.0\/24.*", vtyout)
assertmsg = (
"BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer2"
)
assert len(routes) == 4, assertmsg
assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer2"
for route in routes:
assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time
65 > int(route.split()[3].split(":")[1]) > 55
), assertmsg # minutes of reuse time
# end test_bgp_dampening_profile_group_over_global
def test_bgp_dampening_profile_peer_over_global():
"Test of BGP route-flap dampening profile preferences: peer over global"
# This test verifies that the dampening profile of a peer takes precedence
# over the global dampening profile by flapping the routes of the peer until
# dampened and comparing the reuse times to the one specified in the
# dampening configuration.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info(
"Starting test of BGP route-flap dampening profile preferences: peer over global"
)
# Flapping routes on ExaBGP peer peer3
logger.info(
"Flapping routes on ExaBGP peer peer3 with route-flap dampening enabled"
)
for _ in range(1, 5):
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer3.in", "w")
with pipe:
pipe.write(
"withdraw route 192.168.5{}.0/24 next-hop 192.168.101.5\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
sleep(1) # Give the BGP session on router r1 time to process routes
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer3.in", "w")
with pipe:
pipe.write(
"announce route 192.168.5{}.0/24 next-hop 192.168.101.5\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Check damped paths on r1 for routes of peer3 witn peer profile
logger.info(
"Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer3"
)
sleep(5) # wait 5 seconds for paths to shop up in damp list
vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"')
routes = re.findall(r"\*d 192\.168\.5\d\.0\/24.*", vtyout)
assertmsg = (
"BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer3"
)
assert len(routes) == 4, assertmsg
assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer3"
for route in routes:
assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time
35 > int(route.split()[3].split(":")[1]) > 25
), assertmsg # minutes of reuse time
# end test_bgp_dampening_profile_peer_over_global
def test_bgp_dampening_profile_global():
"Test of BGP route-flap dampening global profile"
# This test verifies the application of the global dampening profile by
# flapping the routes of a peer until dampened and comparing the reuse times
# to the one specified in the dampening configuration.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting test of BGP route-flap dampening global profile")
# Flapping routes on ExaBGP peer peer4
logger.info(
"Flapping routes on ExaBGP peer peer4 with route-flap dampening enabled"
)
for _ in range(1, 5):
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer4.in", "w")
with pipe:
pipe.write(
"withdraw route 192.168.6{}.0/24 next-hop 192.168.101.6\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
sleep(1) # Give the BGP session on router r1 time to process routes
for prefix_iter in range(1, 5):
pipe = open("/run/exabgp_peer4.in", "w")
with pipe:
pipe.write(
"announce route 192.168.6{}.0/24 next-hop 192.168.101.6\n".format(
prefix_iter
)
)
pipe.close()
sleep(0.1) # ExaBGP API command processing delay
# Check damped paths on r1 for routes of peer4 witn global profile
logger.info(
"Checking if router r1 used the global dampening profile on routes flapped by ExaBGP peer peer4"
)
sleep(5) # wait 5 seconds for paths to shop up in damp list
vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"')
routes = re.findall(r"\*d 192\.168\.6\d\.0\/24.*", vtyout)
assertmsg = (
"BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer4"
)
assert len(routes) == 4, assertmsg
assertmsg = "BGP session on router r1 did not use the global dampening profile for a route flapped by ExaBGP peer peer4"
for route in routes:
assert (int(route.split()[3].split(":")[0]) == 1) and ( # hours of reuse time
35 > int(route.split()[3].split(":")[1]) > 25
), assertmsg # minutes of reuse time
# end test_bgp_dampening_profile_global
def test_bgp_dampening_withdaw():
"Test BGP route-flap dampening route withdraw"
# This test verifies that the withrawl of dampened routes from the RIB of
# router r1 was propagated to router r2.
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting test of BGP route-flap dampening route withdraw")
# Check if routes dampened on router r1 have been withdrawn from the RIB on
# router r2
logger.info(
"Checking if routes dampened on router r1 have been withdrawn of RIB on router r2"
)
reffile = os.path.join(CWD, "r2/bgp_damp_withdrawn.json")
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, tgen.gears["r2"], "show ip bgp json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=5, wait=1)
assertmsg = "BGP session on router r2 did not receive withdraw of routes dampened on router r1"
assert res is None, assertmsg
# end test_bgp_dampening_withdaw
def test_bgp_dampening_cleanup():
"BGP route-flap dampening test cleanup"
# This test cleans up after other tests associated with route-flap dampening
# by disabling all dampening configurations, removing added peers and
# peer-groups from the configuration on router r1, and shutting down ExaBGP
# peers peer1, peer2 and peer3.
tgen = get_topogen()
r_1 = tgen.net["r1"]
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Starting BGP route-flap dampening test cleanup")
# Disable all dampening configurations
logger.info("Disabling all dampening configurations")
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no bgp dampening"'
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor group1 dampening"'
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor 192.168.101.3 dampening"'
)
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor 192.168.101.5 dampening"'
)
# Remove ExaBGP peers from configuration of router r1
logger.info("Removing ExaBGP peers from configuration of router r1")
for router_num in range(3, 7):
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.{}"'.format(
router_num
)
)
# Remove peer-group group1 from configuration of router r1
logger.info("Removing peer-group group1 peers from configuration of router r1")
r_1.cmd(
'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor group1 peer-group"'
)
# Stop ExaBGP peers and remove associated named pipes
logger.info("Stopping ExaBGP peers and removing associated named pipes")
for peer_num in range(1, 5):
logger.info("Terminating ExaBGP on peer peer{}".format(peer_num))
peer = tgen.gears["peer{}".format(peer_num)]
logger.info("Removing named pipe of ExaBGP peer peer{}".format(peer_num))
fifo_in = "/var/run/exabgp_peer{}.in".format(peer_num)
peer.stop()
if os.path.exists(fifo_in):
os.remove(fifo_in)
# end test_bgp_dampening_cleanup
def test_bgp_dampening_aftermath():
"BGP route-flap dampening aftermath test"
# This test verifies routers r1 and r2 not being affected by the route-flap
# dampening test series.
tgen = get_topogen()
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Check BGP Summary on routers r1 and r2
for rtr_num in [1, 2]:
logger.info(
"Checking if BGP router on r{} remains unaffected by route-flap dampening tests".format(
rtr_num
)
)
router = tgen.gears["r{}".format(rtr_num)]
reffile = os.path.join(CWD, "r{}/show_bgp.json".format(rtr_num))
expected = json.loads(open(reffile).read())
test_func = functools.partial(
topotest.router_json_cmp, router, "show ip bgp json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=10, wait=2)
assertmsg = "BGP routes on router r{} are wrong after route-flap dampening tests".format(
rtr_num
)
assert res is None, assertmsg
# end test_bgp_dampening_aftermath
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))