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_advertise.h"
#include "bgpd/bgp_vty.h" #include "bgpd/bgp_vty.h"
static void bgp_reuselist_add(struct reuselist *list, /* Global variable to access damping configuration */
struct bgp_damp_info *info) static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
{
assert(info);
SLIST_INSERT_HEAD(list, info, entry);
}
static void bgp_reuselist_del(struct reuselist *list, /* Utility macro to add and delete BGP dampening information to no
struct bgp_damp_info *info) used list. */
{ #define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
assert(info); #define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
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;
}
/* Calculate reuse list index by penalty value. */ /* Calculate reuse list index by penalty value. */
static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc) static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
{ {
unsigned int i; unsigned int i;
unsigned int index; int index;
/* /*
* reuse_limit can't be zero, this is for Coverity * 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, static void bgp_reuse_list_add(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc) struct bgp_damp_config *bdc)
{ {
bgp_damp_info_claim(bdi, bdc); int index;
bdi->index = bgp_reuse_index(bdi->penalty, bdc);
bgp_reuselist_add(&bdc->reuse_list[bdi->index], bdi); 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. */ /* Delete BGP dampening information from reuse list. */
static void bgp_reuse_list_delete(struct bgp_damp_info *bdi) 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,
struct bgp_damp_config *bdc) struct bgp_damp_config *bdc)
{ {
bgp_damp_info_claim(bdi, bdc); if (bdi->next)
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; bdi->next->prev = bdi->prev;
bgp_reuselist_add(&bdc->no_reuse_list, bdi); if (bdi->prev)
} bdi->prev->next = bdi->next;
else
static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi) bdc->reuse_list[bdi->index] = bdi->next;
{
bgp_damp_info_unclaim(bdi);
} }
/* Return decayed penalty value. */ /* 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. */ is evaluated. RFC2439 Section 4.8.7. */
static int bgp_reuse_timer(struct thread *t) static int bgp_reuse_timer(struct thread *t)
{ {
struct bgp_damp_config *bdc = THREAD_ARG(t);
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
struct reuselist plist; struct bgp_damp_info *next;
struct bgp *bgp;
time_t t_now, t_diff; 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, thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
&bdc->t_reuse); &bdc->t_reuse);
t_now = bgp_clock(); t_now = bgp_clock();
/* 1. save a pointer to the current queue head and zero the list head /* 1. save a pointer to the current zeroth queue head and zero the
* list head entry. */ list head entry. */
assert(bdc->reuse_offset < bdc->reuse_list_size); bdi = bdc->reuse_list[bdc->reuse_offset];
plist = bdc->reuse_list[bdc->reuse_offset]; bdc->reuse_list[bdc->reuse_offset] = NULL;
SLIST_INIT(&bdc->reuse_list[bdc->reuse_offset]);
/* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
rotating the circular queue of list-heads. */ rotating the circular queue of list-heads. */
bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size; 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 ) */ /* 3. if ( the saved list head pointer is non-empty ) */
while ((bdi = SLIST_FIRST(&plist)) != NULL) { for (; bdi; bdi = next) {
bgp = bdi->path->peer->bgp; struct bgp *bgp = bdi->path->peer->bgp;
next = bdi->next;
/* Set t-diff = t-now - t-updated. */ /* Set t-diff = t-now - t-updated. */
t_diff = t_now - bdi->t_updated; t_diff = t_now - bdi->t_updated;
@ -226,24 +169,15 @@ static int bgp_reuse_timer(struct thread *t)
bdi->safi); bdi->safi);
} }
if (bdi->penalty <= bdc->reuse_limit / 2.0) { if (bdi->penalty <= bdc->reuse_limit / 2.0)
bgp_reuselist_del(&plist, bdi); bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi);
bgp_damp_info_free(bdi, 1); else
} else { BGP_DAMP_LIST_ADD(bdc, bdi);
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; } else
bgp_reuselist_switch(&plist, bdi,
&bdc->no_reuse_list);
}
} else {
/* Re-insert into another list (See RFC2439 Section /* Re-insert into another list (See RFC2439 Section
* 4.8.6). */ * 4.8.6). */
bdi->index = bgp_reuse_index(bdi->penalty, bdc); bgp_reuse_list_add(bdi, bdc);
bgp_reuselist_switch(&plist, bdi,
&bdc->reuse_list[bdi->index]);
} }
}
assert(SLIST_EMPTY(&plist));
return 0; return 0;
} }
@ -255,13 +189,10 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
time_t t_now; time_t t_now;
struct bgp_damp_info *bdi = NULL; struct bgp_damp_info *bdi = NULL;
unsigned int last_penalty = 0; unsigned int last_penalty = 0;
struct bgp_damp_config *bdc; struct bgp_damp_config *bdc = &damp[afi][safi];
bdc = get_active_bdc_from_pi(path, afi, safi);
if (!bdc)
return BGP_DAMP_USED;
t_now = bgp_clock(); t_now = bgp_clock();
/* Processing Unreachable Messages. */ /* Processing Unreachable Messages. */
if (path->extra) if (path->extra)
bdi = path->extra->damp_info; 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->flap = 1;
bdi->start_time = t_now; bdi->start_time = t_now;
bdi->suppress_time = 0; bdi->suppress_time = 0;
bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; bdi->index = -1;
bdi->afi = afi; bdi->afi = afi;
bdi->safi = safi; bdi->safi = safi;
(bgp_path_info_extra_get(path))->damp_info = bdi; (bgp_path_info_extra_get(path))->damp_info = bdi;
bgp_no_reuse_list_add(bdi, bdc); BGP_DAMP_LIST_ADD(bdc, bdi);
} else { } 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; last_penalty = bdi->penalty;
/* 1. Set t-diff = t-now - t-updated. */ /* 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. */ /* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) { if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) {
/* If decay rate isn't equal to 0, reinsert brn. */ /* If decay rate isn't equal to 0, reinsert brn. */
if (bdi->penalty != last_penalty) { if (bdi->penalty != last_penalty && bdi->index >= 0) {
bgp_reuse_list_delete(bdi); bgp_reuse_list_delete(bdi, bdc);
bgp_reuse_list_add(bdi, bdc); bgp_reuse_list_add(bdi, bdc);
} }
return BGP_DAMP_SUPPRESSED; 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) { if (bdi->penalty >= bdc->suppress_value) {
bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED); bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED);
bdi->suppress_time = t_now; bdi->suppress_time = t_now;
bgp_no_reuse_list_delete(bdi); BGP_DAMP_LIST_DEL(bdc, bdi);
bgp_reuse_list_add(bdi, bdc); bgp_reuse_list_add(bdi, bdc);
} }
return BGP_DAMP_USED; 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; time_t t_now;
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
int status; int status;
struct bgp_damp_config *bdc; struct bgp_damp_config *bdc = &damp[afi][safi];
bdc = get_active_bdc_from_pi(path, afi, safi);
assert(bdc);
if (!path->extra || !((bdi = path->extra->damp_info))) if (!path->extra || !((bdi = path->extra->damp_info)))
return BGP_DAMP_USED; 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) else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
&& (bdi->penalty < bdc->reuse_limit)) { && (bdi->penalty < bdc->reuse_limit)) {
bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED); bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED);
bgp_reuse_list_delete(bdi); bgp_reuse_list_delete(bdi, bdc);
bgp_no_reuse_list_add(bdi, bdc); BGP_DAMP_LIST_ADD(bdc, bdi);
bdi->suppress_time = 0; bdi->suppress_time = 0;
status = BGP_DAMP_USED; status = BGP_DAMP_USED;
} else } 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) if (bdi->penalty > bdc->reuse_limit / 2.0)
bdi->t_updated = t_now; bdi->t_updated = t_now;
else { else
bgp_damp_info_unclaim(bdi); bgp_damp_info_free(bdi, 0, afi, safi);
bgp_damp_info_free(bdi, 0);
}
return status; 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) { if (!bdi)
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
return; return;
}
bdi->path->extra->damp_info = NULL; path = bdi->path;
bgp_path_info_unset_flag(bdi->dest, 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); BGP_PATH_HISTORY | BGP_PATH_DAMPED);
if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) 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, 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 = bdc->reuse_list =
XCALLOC(MTYPE_BGP_DAMP_ARRAY, XCALLOC(MTYPE_BGP_DAMP_ARRAY,
bdc->reuse_list_size * sizeof(struct reuselist)); bdc->reuse_list_size * sizeof(struct bgp_reuse_node *));
/* Reuse-array computations */ /* Reuse-array computations */
bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
sizeof(int) * bdc->reuse_index_size); 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, 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) 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 (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
if (bdc->half_life == half && bdc->reuse_limit == reuse 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); SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
bgp_damp_parameter_set(half, reuse, suppress, max, bdc); bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
bdc->afi = afi;
bdc->safi = safi;
/* Register reuse timer. */ /* Register reuse timer. */
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE, 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; return 0;
} }
/* Clean all the bgp_damp_info stored in reuse_list and no_reuse_list. */ static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
afi_t afi, safi_t safi)
{ {
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 */ /* Free decay array */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array); XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array);
bdc->decay_array_size = 0; 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); XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
bdc->reuse_index_size = 0; bdc->reuse_index_size = 0;
/* Free reuse list array. */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list); XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
bdc->reuse_list_size = 0; bdc->reuse_list_size = 0;
THREAD_OFF(bdc->t_reuse);
} }
/* Disable route flap dampening for a bgp instance. /* Clean all the bgp_damp_info stored in reuse_list. */
* void bgp_damp_info_clean(afi_t afi, safi_t safi)
* Please note that this function also gets used to free memory when deleting a {
* bgp instance. 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) int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
{ {
struct bgp_damp_config *bdc; struct bgp_damp_config *bdc = &damp[afi][safi];
bdc = &bgp->damp[afi][safi];
if (!bdc)
return 0;
/* If it wasn't enabled, there's nothing to do. */ /* If it wasn't enabled, there's nothing to do. */
if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
return 0; return 0;
/* Cancel reuse event. */ /* Cancel reuse event. */
thread_cancel(&bdc->t_reuse); thread_cancel(&(bdc->t_reuse));
/* Clean BGP dampening information. */ /* 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); UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
return 0; return 0;
} }
void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi, void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi)
safi_t safi)
{ {
struct bgp_damp_config *bdc; if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60
&& damp[afi][safi].reuse_limit == DEFAULT_REUSE
bdc = &bgp->damp[afi][safi]; && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
if (bdc->half_life == DEFAULT_HALF_LIFE * 60 && damp[afi][safi].max_suppress_time
&& bdc->reuse_limit == DEFAULT_REUSE == damp[afi][safi].half_life * 4)
&& bdc->suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4)
vty_out(vty, " bgp dampening\n"); vty_out(vty, " bgp dampening\n");
else if (bdc->half_life != DEFAULT_HALF_LIFE * 60 else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60
&& bdc->reuse_limit == DEFAULT_REUSE && damp[afi][safi].reuse_limit == DEFAULT_REUSE
&& bdc->suppress_value == DEFAULT_SUPPRESS && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
&& bdc->max_suppress_time == bdc->half_life * 4) && damp[afi][safi].max_suppress_time
vty_out(vty, " bgp dampening %lld\n", bdc->half_life / 60LL); == damp[afi][safi].half_life * 4)
vty_out(vty, " bgp dampening %lld\n",
damp[afi][safi].half_life / 60LL);
else else
vty_out(vty, " bgp dampening %lld %d %d %lld\n", vty_out(vty, " bgp dampening %lld %d %d %lld\n",
bdc->half_life / 60LL, bdc->reuse_limit, damp[afi][safi].half_life / 60LL,
bdc->suppress_value, bdc->max_suppress_time / 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, static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
unsigned int penalty, char *buf, size_t len, afi_t afi, safi_t safi,
size_t len, bool use_json, bool use_json, json_object *json)
json_object *json)
{ {
time_t reuse_time = 0; time_t reuse_time = 0;
struct tm tm; struct tm tm;
int time_store = 0; int time_store = 0;
if (penalty > bdc->reuse_limit) { if (penalty > damp[afi][safi].reuse_limit) {
reuse_time = (int)(DELTA_T reuse_time = (int)(DELTA_T
* ((log((double)bdc->reuse_limit / penalty)) * ((log((double)damp[afi][safi].reuse_limit
/ (log(bdc->decay_array[1])))); / penalty))
/ (log(damp[afi][safi].decay_array[1]))));
if (reuse_time > bdc->max_suppress_time) if (reuse_time > damp[afi][safi].max_suppress_time)
reuse_time = bdc->max_suppress_time; reuse_time = damp[afi][safi].max_suppress_time;
gmtime_r(&reuse_time, &tm); gmtime_r(&reuse_time, &tm);
} else } else
@ -649,15 +569,14 @@ static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc,
return buf; return buf;
} }
void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
struct bgp_path_info *path, afi_t afi, safi_t safi, safi_t safi, json_object *json_path)
json_object *json_path)
{ {
struct bgp_damp_info *bdi; struct bgp_damp_info *bdi;
time_t t_now, t_diff; time_t t_now, t_diff;
char timebuf[BGP_UPTIME_LEN]; char timebuf[BGP_UPTIME_LEN];
int penalty; int penalty;
struct bgp_damp_config *bdc = &bgp->damp[afi][safi]; struct bgp_damp_config *bdc = &damp[afi][safi];
if (!path->extra) if (!path->extra)
return; return;
@ -683,8 +602,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
bgp_get_reuse_time(bdc, penalty, timebuf, bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN,
BGP_UPTIME_LEN, 1, json_path); afi, safi, 1, json_path);
} else { } else {
vty_out(vty, vty_out(vty,
" Dampinfo: penalty %d, flapped %d times in %s", " 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) if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, ", reuse in %s", vty_out(vty, ", reuse in %s",
bgp_get_reuse_time(bdc, penalty, timebuf, bgp_get_reuse_time(penalty, timebuf,
BGP_UPTIME_LEN, 0, BGP_UPTIME_LEN, afi, safi, 0,
json_path)); json_path));
vty_out(vty, "\n"); vty_out(vty, "\n");
} }
} }
const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi, char *timebuf, size_t len, afi_t afi,
safi_t safi, bool use_json, 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; struct bgp_damp_info *bdi;
time_t t_now, t_diff; time_t t_now, t_diff;
int penalty; int penalty;
struct bgp_damp_config *bdc; struct bgp_damp_config *bdc = &damp[afi][safi];
bdc = get_active_bdc_from_pi(path, afi, safi);
if (!bdc)
return NULL;
if (!path->extra) if (!path->extra)
return NULL; 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, /* If dampening is not enabled or there is no dampening information,
return immediately. */ return immediately. */
if (!bdi) if (!bdc || !bdi)
return NULL; return NULL;
/* Calculate new penalty. */ /* 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; t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc); 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, static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty,
afi_t afi, safi_t safi) afi_t afi, safi_t safi)
{ {
struct bgp_damp_config *bdc;
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) { 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", vty_out(vty, "Half-life time: %lld min\n",
(long long)bdc->half_life / 60); (long long)damp[afi][safi].half_life / 60);
vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit); vty_out(vty, "Reuse penalty: %d\n",
vty_out(vty, "Suppress penalty: %d\n", bdc->suppress_value); 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", vty_out(vty, "Max suppress time: %lld min\n",
(long long)bdc->max_suppress_time / 60); (long long)damp[afi][safi].max_suppress_time / 60);
vty_out(vty, "Max suppress penalty: %u\n", bdc->ceiling); vty_out(vty, "Max suppress penalty: %u\n",
damp[afi][safi].ceiling);
vty_out(vty, "\n"); vty_out(vty, "\n");
} else } else
vty_out(vty, "dampening not enabled for %s\n", 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) uint16_t show_flags)
{ {
struct bgp *bgp; struct bgp *bgp;
bgp = bgp_get_default(); bgp = bgp_get_default();
if (bgp == NULL) { if (bgp == NULL) {
vty_out(vty, "No BGP process is configured\n"); vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING; return CMD_WARNING;
@ -803,132 +718,3 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
} }
return CMD_SUCCESS; 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. */ /* Structure maintained on a per-route basis. */
struct bgp_damp_info { 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. */ /* Figure-of-merit. */
unsigned int penalty; unsigned int penalty;
@ -40,9 +45,6 @@ struct bgp_damp_info {
/* Time of route start to be suppressed. */ /* Time of route start to be suppressed. */
time_t suppress_time; time_t suppress_time;
/* Back reference to associated dampening configuration. */
struct bgp_damp_config *config;
/* Back reference to bgp_path_info. */ /* Back reference to bgp_path_info. */
struct bgp_path_info *path; struct bgp_path_info *path;
@ -51,8 +53,6 @@ struct bgp_damp_info {
/* Current index in the reuse_list. */ /* Current index in the reuse_list. */
int index; int index;
#define BGP_DAMP_NO_REUSE_LIST_INDEX \
(-1) /* index for elements on no_reuse_list */
/* Last time message type. */ /* Last time message type. */
uint8_t lastrecord; uint8_t lastrecord;
@ -61,12 +61,8 @@ struct bgp_damp_info {
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
SLIST_ENTRY(bgp_damp_info) entry;
}; };
SLIST_HEAD(reuselist, bgp_damp_info);
/* Specified parameter set configuration. */ /* Specified parameter set configuration. */
struct bgp_damp_config { struct bgp_damp_config {
/* Value over which routes suppressed. */ /* Value over which routes suppressed. */
@ -104,11 +100,11 @@ struct bgp_damp_config {
int *reuse_index; int *reuse_index;
/* Reuse list array per-set based. */ /* Reuse list array per-set based. */
struct reuselist *reuse_list; struct bgp_damp_info **reuse_list;
unsigned int reuse_offset; int reuse_offset;
/* All dampening information which is not on reuse list. */ /* 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. */ /* Reuse timer thread per-set base. */
struct thread *t_reuse; struct thread *t_reuse;
@ -136,8 +132,6 @@ struct bgp_damp_config {
#define REUSE_LIST_SIZE 256 #define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024 #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, extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int,
unsigned int, time_t); unsigned int, time_t);
extern int bgp_damp_disable(struct bgp *, afi_t, safi_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); afi_t afi, safi_t safi, int attr_change);
extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
afi_t afi, safi_t saff); afi_t afi, safi_t saff);
extern void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw); extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw,
extern void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
afi_t afi, safi_t safi); afi_t afi, safi_t safi);
extern void bgp_damp_config_clean(struct bgp_damp_config *bdc); 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 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, extern void bgp_config_write_damp(struct vty *, afi_t afi, safi_t safi);
safi_t safi); extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
extern void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, json_object *json_path);
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, extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
struct bgp_path_info *path, struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi, 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); json_object *json);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t, extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t,
uint16_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 */ #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, PEER_CONF_IF, "BGP peer config interface");
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info"); DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info");
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array"); 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_REGEXP, "BGP regexp");
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate"); DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate");
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address"); 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(PEER_CONF_IF);
DECLARE_MTYPE(BGP_DAMP_INFO); DECLARE_MTYPE(BGP_DAMP_INFO);
DECLARE_MTYPE(BGP_DAMP_ARRAY); DECLARE_MTYPE(BGP_DAMP_ARRAY);
DECLARE_MTYPE(BGP_DAMP_REUSELIST);
DECLARE_MTYPE(BGP_REGEXP); DECLARE_MTYPE(BGP_REGEXP);
DECLARE_MTYPE(BGP_AGGREGATE); DECLARE_MTYPE(BGP_AGGREGATE);
DECLARE_MTYPE(BGP_ADDR); DECLARE_MTYPE(BGP_ADDR);

View File

@ -218,11 +218,11 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
return; return;
e = *extra; e = *extra;
if (e->damp_info) if (e->damp_info)
bgp_damp_info_free(e->damp_info, 0); bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
e->damp_info = NULL; e->damp_info->safi);
e->damp_info = NULL;
if (e->parent) { if (e->parent) {
struct bgp_path_info *bpi = (struct bgp_path_info *)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 /* apply dampening, if result is suppressed, we'll be retaining
* the bgp_path_info in the RIB for historical reference. * the bgp_path_info in the RIB for historical reference.
*/ */
if (peer->sort == BGP_PEER_EBGP) { if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
if (get_active_bdc_from_pi(pi, afi, safi)) { && peer->sort == BGP_PEER_EBGP)
if (bgp_damp_withdraw(pi, dest, afi, safi, 0) if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
== BGP_DAMP_SUPPRESSED) { == BGP_DAMP_SUPPRESSED) {
bgp_aggregate_decrement(peer->bgp, p, pi, afi, bgp_aggregate_decrement(peer->bgp, p, pi, afi,
safi); safi);
return; return;
} }
}
}
#ifdef ENABLE_BGP_VNC #ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) { 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, || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
num_labels * sizeof(mpls_label_t)) num_labels * sizeof(mpls_label_t))
== 0)) { == 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 && peer->sort == BGP_PEER_EBGP
&& CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
if (bgp_debug_update(peer, p, NULL, 1)) { 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); bgp_aggregate_decrement(bgp, p, pi, afi, safi);
/* Update bgp route dampening information. */ /* 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) { && peer->sort == BGP_PEER_EBGP) {
/* This is implicit withdraw so we should update /* This is implicit withdraw so we should update
* dampening information. dampening
*/ information. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
bgp_damp_withdraw(pi, dest, afi, safi, 1); 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 #endif
/* Update bgp route dampening information. */ /* 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) { && peer->sort == BGP_PEER_EBGP) {
/* Now we do normal update dampening. */ /* Now we do normal update dampening. */
ret = bgp_damp_update(pi, dest, afi, safi); 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) 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 */ /* Remote Label */
if (path->extra && bgp_is_valid_label(&path->extra->label[0]) 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; pi_temp = pi->next;
bgp_damp_info_free( bgp_damp_info_free(
pi->extra->damp_info, pi->extra->damp_info,
1); 1, afi, safi);
pi = pi_temp; pi = pi_temp;
} else } else
pi = pi->next; pi = pi->next;
@ -14667,24 +14666,9 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
while (pi) { while (pi) {
if (pi->extra && pi->extra->damp_info) { if (pi->extra && pi->extra->damp_info) {
pi_temp = pi->next; 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( bgp_damp_info_free(
pi->extra->damp_info, pi->extra->damp_info,
1); 1, afi, safi);
pi = pi_temp; pi = pi_temp;
} else } else
pi = pi->next; pi = pi->next;
@ -14706,9 +14690,7 @@ DEFUN (clear_ip_bgp_dampening,
BGP_STR BGP_STR
"Clear route flap dampening information\n") "Clear route flap dampening information\n")
{ {
VTY_DECLVAR_CONTEXT(bgp, bgp); bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
SAFI_UNICAST);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -8046,93 +8046,6 @@ DEFPY(
return CMD_SUCCESS; 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, static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
struct ecommunity **list, bool is_rt6) 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. */ /* 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. */ /* BGP flag dampening. */
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_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)) for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi); 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, &neighbor_allowas_in_cmd);
install_element(BGP_EVPN_NODE, &no_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. */ /* address-family commands. */
install_element(BGP_NODE, &address_family_ipv4_safi_cmd); install_element(BGP_NODE, &address_family_ipv4_safi_cmd);
install_element(BGP_NODE, &address_family_ipv6_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) if (peer->bfd_config)
bgp_peer_remove_bfd_config(peer); 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 /* If this peer belongs to peer group, clear up the
relationship. */ relationship. */
if (peer->group) { if (peer->group) {
@ -3603,11 +3595,6 @@ int bgp_delete(struct bgp *bgp)
BGP_TIMER_OFF(gr_info->t_route_select); 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_DEBUG(zebra, ZEBRA)) {
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
zlog_debug("Deleting Default VRF"); zlog_debug("Deleting Default VRF");

View File

@ -44,7 +44,6 @@
#include "bgp_labelpool.h" #include "bgp_labelpool.h"
#include "bgp_addpath_types.h" #include "bgp_addpath_types.h"
#include "bgp_nexthop.h" #include "bgp_nexthop.h"
#include "bgp_damp.h"
#include "bgp_io.h" #include "bgp_io.h"
#include "lib/bfd.h" #include "lib/bfd.h"
@ -752,9 +751,6 @@ struct bgp {
uint32_t condition_filter_count; uint32_t condition_filter_count;
struct thread *t_condition_check; struct thread *t_condition_check;
/* BGP route flap dampening configuration */
struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
/* BGP VPN SRv6 backend */ /* BGP VPN SRv6 backend */
bool srv6_enabled; bool srv6_enabled;
char srv6_locator_name[SRV6_LOCNAME_SIZE]; char srv6_locator_name[SRV6_LOCNAME_SIZE];
@ -1314,9 +1310,6 @@ struct peer {
/* Last update packet sent time */ /* Last update packet sent time */
time_t pkt_stime[AFI_MAX][SAFI_MAX]; 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 */ /* Peer Per AF flags */
/* /*
* Please consult the comments for *flags_override*, *flags_invert* and * 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_SEND_LARGE_COMMUNITY (1U << 26) /* Send large Communities */
#define PEER_FLAG_MAX_PREFIX_OUT (1U << 27) /* outgoing maximum prefix */ #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_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]; 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 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 This command enables BGP route-flap dampening and specifies dampening parameters.
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.
half-life half-life
Half-life time for the penalty in minutes (default value: 15). Half-life time for the penalty
reuse-threshold reuse-threshold
Value to start reusing a route (default value: 750). Value to start reusing a route
suppress-threshold suppress-threshold
Value to start suppressing a route (default value: 2000). Value to start suppressing a route
max-suppress max-suppress
Maximum duration to suppress a stable route in minutes (default value: Maximum duration to suppress a stable route
60).
The route-flap damping algorithm is compatible with :rfc:`2439`. The use of 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 At the moment, route-flap dampening is not working per VRF and is working only
for IPv4 unicast and multicast. 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:: .. seealso::
https://www.ripe.net/publications/docs/ripe-378 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 pytest
import re import re
import time import time
from time import sleep
# Save the Current Working Directory to find configuration files. # Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__)) CWD = os.path.dirname(os.path.realpath(__file__))
@ -67,14 +66,6 @@ class BGPFeaturesTopo1(Topo):
for rtrNum in range(1, 6): for rtrNum in range(1, 6):
tgen.add_router("r{}".format(rtrNum)) 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 # Setup Switches and connections
for swNum in range(1, 11): for swNum in range(1, 11):
tgen.add_switch("sw{}".format(swNum)) tgen.add_switch("sw{}".format(swNum))
@ -100,12 +91,6 @@ class BGPFeaturesTopo1(Topo):
tgen.gears["r2"].add_link(tgen.gears["sw5"]) tgen.gears["r2"].add_link(tgen.gears["sw5"])
tgen.gears["r5"].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 # 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__": if __name__ == "__main__":
args = ["-s"] + sys.argv[1:] args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args)) sys.exit(pytest.main(args))