mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 13:04:01 +00:00
Merge pull request #9256 from idryzhov/dampening-revert
BGP per-peer dampening revert
This commit is contained in:
commit
883da9f5ec
526
bgpd/bgp_damp.c
526
bgpd/bgp_damp.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
109
bgpd/bgp_vty.c
109
bgpd/bgp_vty.c
@ -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);
|
||||
|
13
bgpd/bgpd.c
13
bgpd/bgpd.c
@ -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");
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
@ -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" } ]
|
||||
}
|
||||
}
|
@ -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"}
|
||||
}
|
||||
}
|
||||
}
|
@ -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" } ]
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user