mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 07:15:33 +00:00
bgpd: Rework BGP dampening to be per AFI/SAFI
Before we had: ! router bgp 65031 bgp dampening 1 2 3 4 ! exit2-debian-9(config)# router bgp 65031 exit2-debian-9(config-router)# address-family ipv4 multicast exit2-debian-9(config-router-af)# bgp dampening 5 6 7 8 exit2-debian-9(config-router-af)# end exit2-debian-9# show running-config ! router bgp 65031 bgp dampening 1 2 3 4 ! After fix: ! router bgp 65031 neighbor 192.168.1.2 remote-as 100 ! address-family ipv4 unicast bgp dampening 1 2 3 4 exit-address-family ! address-family ipv4 multicast bgp dampening 5 6 7 8 exit-address-family ! exit2-debian-9# show ip bgp ipv4 unicast dampening parameters Half-life time: 1 min Reuse penalty: 2 Suppress penalty: 3 Max suppress time: 4 min Max suppress penalty: 32 exit2-debian-9# show ip bgp ipv4 multicast dampening parameters Half-life time: 5 min Reuse penalty: 6 Suppress penalty: 7 Max suppress time: 8 min Max suppress penalty: 18 Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
parent
4875c110d3
commit
72a0f11da2
385
bgpd/bgp_damp.c
385
bgpd/bgp_damp.c
@ -37,8 +37,7 @@
|
|||||||
#include "bgpd/bgp_advertise.h"
|
#include "bgpd/bgp_advertise.h"
|
||||||
|
|
||||||
/* Global variable to access damping configuration */
|
/* Global variable to access damping configuration */
|
||||||
struct bgp_damp_config bgp_damp_cfg;
|
static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
|
||||||
static struct bgp_damp_config *damp = &bgp_damp_cfg;
|
|
||||||
|
|
||||||
/* Utility macro to add and delete BGP dampening information to no
|
/* Utility macro to add and delete BGP dampening information to no
|
||||||
used list. */
|
used list. */
|
||||||
@ -46,49 +45,51 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg;
|
|||||||
#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(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. */
|
/* Calculate reuse list index by penalty value. */
|
||||||
static int bgp_reuse_index(int penalty)
|
static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
i = (int)(((double)penalty / damp->reuse_limit - 1.0)
|
i = (int)(((double)penalty / bdc->reuse_limit - 1.0)
|
||||||
* damp->scale_factor);
|
* bdc->scale_factor);
|
||||||
|
|
||||||
if (i >= damp->reuse_index_size)
|
if (i >= bdc->reuse_index_size)
|
||||||
i = damp->reuse_index_size - 1;
|
i = bdc->reuse_index_size - 1;
|
||||||
|
|
||||||
index = damp->reuse_index[i] - damp->reuse_index[0];
|
index = bdc->reuse_index[i] - bdc->reuse_index[0];
|
||||||
|
|
||||||
return (damp->reuse_offset + index) % damp->reuse_list_size;
|
return (bdc->reuse_offset + index) % bdc->reuse_list_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add BGP dampening information to reuse list. */
|
/* Add BGP dampening information to reuse list. */
|
||||||
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)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
index = bdi->index = bgp_reuse_index(bdi->penalty);
|
index = bdi->index = bgp_reuse_index(bdi->penalty, bdc);
|
||||||
|
|
||||||
bdi->prev = NULL;
|
bdi->prev = NULL;
|
||||||
bdi->next = damp->reuse_list[index];
|
bdi->next = bdc->reuse_list[index];
|
||||||
if (damp->reuse_list[index])
|
if (bdc->reuse_list[index])
|
||||||
damp->reuse_list[index]->prev = bdi;
|
bdc->reuse_list[index]->prev = bdi;
|
||||||
damp->reuse_list[index] = 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,
|
||||||
|
struct bgp_damp_config *bdc)
|
||||||
{
|
{
|
||||||
if (bdi->next)
|
if (bdi->next)
|
||||||
bdi->next->prev = bdi->prev;
|
bdi->next->prev = bdi->prev;
|
||||||
if (bdi->prev)
|
if (bdi->prev)
|
||||||
bdi->prev->next = bdi->next;
|
bdi->prev->next = bdi->next;
|
||||||
else
|
else
|
||||||
damp->reuse_list[bdi->index] = bdi->next;
|
bdc->reuse_list[bdi->index] = bdi->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return decayed penalty value. */
|
/* Return decayed penalty value. */
|
||||||
int bgp_damp_decay(time_t tdiff, int penalty)
|
int bgp_damp_decay(time_t tdiff, int penalty, struct bgp_damp_config *bdc)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -97,10 +98,10 @@ int bgp_damp_decay(time_t tdiff, int penalty)
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
return penalty;
|
return penalty;
|
||||||
|
|
||||||
if (i >= damp->decay_array_size)
|
if (i >= bdc->decay_array_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (int)(penalty * damp->decay_array[i]);
|
return (int)(penalty * bdc->decay_array[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler of reuse timer event. Each route in the current reuse-list
|
/* Handler of reuse timer event. Each route in the current reuse-list
|
||||||
@ -111,20 +112,22 @@ static int bgp_reuse_timer(struct thread *t)
|
|||||||
struct bgp_damp_info *next;
|
struct bgp_damp_info *next;
|
||||||
time_t t_now, t_diff;
|
time_t t_now, t_diff;
|
||||||
|
|
||||||
damp->t_reuse = NULL;
|
struct bgp_damp_config *bdc = THREAD_ARG(t);
|
||||||
thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
|
|
||||||
&damp->t_reuse);
|
bdc->t_reuse = NULL;
|
||||||
|
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
|
||||||
|
&bdc->t_reuse);
|
||||||
|
|
||||||
t_now = bgp_clock();
|
t_now = bgp_clock();
|
||||||
|
|
||||||
/* 1. save a pointer to the current zeroth queue head and zero the
|
/* 1. save a pointer to the current zeroth queue head and zero the
|
||||||
list head entry. */
|
list head entry. */
|
||||||
bdi = damp->reuse_list[damp->reuse_offset];
|
bdi = bdc->reuse_list[bdc->reuse_offset];
|
||||||
damp->reuse_list[damp->reuse_offset] = NULL;
|
bdc->reuse_list[bdc->reuse_offset] = NULL;
|
||||||
|
|
||||||
/* 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. */
|
||||||
damp->reuse_offset = (damp->reuse_offset + 1) % damp->reuse_list_size;
|
bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size;
|
||||||
|
|
||||||
/* 3. if ( the saved list head pointer is non-empty ) */
|
/* 3. if ( the saved list head pointer is non-empty ) */
|
||||||
for (; bdi; bdi = next) {
|
for (; bdi; bdi = next) {
|
||||||
@ -137,13 +140,13 @@ static int bgp_reuse_timer(struct thread *t)
|
|||||||
|
|
||||||
/* Set figure-of-merit = figure-of-merit * decay-array-ok
|
/* Set figure-of-merit = figure-of-merit * decay-array-ok
|
||||||
* [t-diff] */
|
* [t-diff] */
|
||||||
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
|
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
|
||||||
|
|
||||||
/* Set t-updated = t-now. */
|
/* Set t-updated = t-now. */
|
||||||
bdi->t_updated = t_now;
|
bdi->t_updated = t_now;
|
||||||
|
|
||||||
/* if (figure-of-merit < reuse). */
|
/* if (figure-of-merit < reuse). */
|
||||||
if (bdi->penalty < damp->reuse_limit) {
|
if (bdi->penalty < bdc->reuse_limit) {
|
||||||
/* Reuse the route. */
|
/* Reuse the route. */
|
||||||
bgp_path_info_unset_flag(bdi->rn, bdi->path,
|
bgp_path_info_unset_flag(bdi->rn, bdi->path,
|
||||||
BGP_PATH_DAMPED);
|
BGP_PATH_DAMPED);
|
||||||
@ -158,14 +161,14 @@ static int bgp_reuse_timer(struct thread *t)
|
|||||||
bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
|
bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdi->penalty <= damp->reuse_limit / 2.0)
|
if (bdi->penalty <= bdc->reuse_limit / 2.0)
|
||||||
bgp_damp_info_free(bdi, 1);
|
bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi);
|
||||||
else
|
else
|
||||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
BGP_DAMP_LIST_ADD(bdc, bdi);
|
||||||
} else
|
} else
|
||||||
/* Re-insert into another list (See RFC2439 Section
|
/* Re-insert into another list (See RFC2439 Section
|
||||||
* 4.8.6). */
|
* 4.8.6). */
|
||||||
bgp_reuse_list_add(bdi);
|
bgp_reuse_list_add(bdi, bdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -178,6 +181,7 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
|||||||
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 = &damp[afi][safi];
|
||||||
|
|
||||||
t_now = bgp_clock();
|
t_now = bgp_clock();
|
||||||
|
|
||||||
@ -206,18 +210,18 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
|||||||
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_DAMP_LIST_ADD(damp, bdi);
|
BGP_DAMP_LIST_ADD(bdc, bdi);
|
||||||
} else {
|
} else {
|
||||||
last_penalty = bdi->penalty;
|
last_penalty = bdi->penalty;
|
||||||
|
|
||||||
/* 1. Set t-diff = t-now - t-updated. */
|
/* 1. Set t-diff = t-now - t-updated. */
|
||||||
bdi->penalty =
|
bdi->penalty = (bgp_damp_decay(t_now - bdi->t_updated,
|
||||||
(bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty)
|
bdi->penalty, bdc)
|
||||||
+ (attr_change ? DEFAULT_PENALTY / 2
|
+ (attr_change ? DEFAULT_PENALTY / 2
|
||||||
: DEFAULT_PENALTY));
|
: DEFAULT_PENALTY));
|
||||||
|
|
||||||
if (bdi->penalty > damp->ceiling)
|
if (bdi->penalty > bdc->ceiling)
|
||||||
bdi->penalty = damp->ceiling;
|
bdi->penalty = bdc->ceiling;
|
||||||
|
|
||||||
bdi->flap++;
|
bdi->flap++;
|
||||||
}
|
}
|
||||||
@ -234,19 +238,19 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
|||||||
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 && bdi->index >= 0) {
|
if (bdi->penalty != last_penalty && bdi->index >= 0) {
|
||||||
bgp_reuse_list_delete(bdi);
|
bgp_reuse_list_delete(bdi, bdc);
|
||||||
bgp_reuse_list_add(bdi);
|
bgp_reuse_list_add(bdi, bdc);
|
||||||
}
|
}
|
||||||
return BGP_DAMP_SUPPRESSED;
|
return BGP_DAMP_SUPPRESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not suppressed before, do annonunce this withdraw and
|
/* If not suppressed before, do annonunce this withdraw and
|
||||||
insert into reuse_list. */
|
insert into reuse_list. */
|
||||||
if (bdi->penalty >= damp->suppress_value) {
|
if (bdi->penalty >= bdc->suppress_value) {
|
||||||
bgp_path_info_set_flag(rn, path, BGP_PATH_DAMPED);
|
bgp_path_info_set_flag(rn, path, BGP_PATH_DAMPED);
|
||||||
bdi->suppress_time = t_now;
|
bdi->suppress_time = t_now;
|
||||||
BGP_DAMP_LIST_DEL(damp, bdi);
|
BGP_DAMP_LIST_DEL(bdc, bdi);
|
||||||
bgp_reuse_list_add(bdi);
|
bgp_reuse_list_add(bdi, bdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BGP_DAMP_USED;
|
return BGP_DAMP_USED;
|
||||||
@ -258,6 +262,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi,
|
|||||||
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 = &damp[afi][safi];
|
||||||
|
|
||||||
if (!path->extra || !((bdi = path->extra->damp_info)))
|
if (!path->extra || !((bdi = path->extra->damp_info)))
|
||||||
return BGP_DAMP_USED;
|
return BGP_DAMP_USED;
|
||||||
@ -266,76 +271,35 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi,
|
|||||||
bgp_path_info_unset_flag(rn, path, BGP_PATH_HISTORY);
|
bgp_path_info_unset_flag(rn, path, BGP_PATH_HISTORY);
|
||||||
|
|
||||||
bdi->lastrecord = BGP_RECORD_UPDATE;
|
bdi->lastrecord = BGP_RECORD_UPDATE;
|
||||||
bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty);
|
bdi->penalty =
|
||||||
|
bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty, bdc);
|
||||||
|
|
||||||
if (!CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
if (!CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
||||||
&& (bdi->penalty < damp->suppress_value))
|
&& (bdi->penalty < bdc->suppress_value))
|
||||||
status = BGP_DAMP_USED;
|
status = BGP_DAMP_USED;
|
||||||
else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
|
||||||
&& (bdi->penalty < damp->reuse_limit)) {
|
&& (bdi->penalty < bdc->reuse_limit)) {
|
||||||
bgp_path_info_unset_flag(rn, path, BGP_PATH_DAMPED);
|
bgp_path_info_unset_flag(rn, path, BGP_PATH_DAMPED);
|
||||||
bgp_reuse_list_delete(bdi);
|
bgp_reuse_list_delete(bdi, bdc);
|
||||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
BGP_DAMP_LIST_ADD(bdc, bdi);
|
||||||
bdi->suppress_time = 0;
|
bdi->suppress_time = 0;
|
||||||
status = BGP_DAMP_USED;
|
status = BGP_DAMP_USED;
|
||||||
} else
|
} else
|
||||||
status = BGP_DAMP_SUPPRESSED;
|
status = BGP_DAMP_SUPPRESSED;
|
||||||
|
|
||||||
if (bdi->penalty > damp->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_free(bdi, 0);
|
bgp_damp_info_free(bdi, 0, afi, safi);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove dampening information and history route. */
|
void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
|
||||||
int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi)
|
safi_t safi)
|
||||||
{
|
|
||||||
time_t t_now, t_diff;
|
|
||||||
struct bgp_damp_info *bdi;
|
|
||||||
|
|
||||||
assert(path->extra && path->extra->damp_info);
|
|
||||||
|
|
||||||
t_now = bgp_clock();
|
|
||||||
bdi = path->extra->damp_info;
|
|
||||||
|
|
||||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
|
|
||||||
t_diff = t_now - bdi->suppress_time;
|
|
||||||
|
|
||||||
if (t_diff >= damp->max_suppress_time) {
|
|
||||||
bgp_path_info_unset_flag(bdi->rn, path,
|
|
||||||
BGP_PATH_DAMPED);
|
|
||||||
bgp_reuse_list_delete(bdi);
|
|
||||||
BGP_DAMP_LIST_ADD(damp, bdi);
|
|
||||||
bdi->penalty = damp->reuse_limit;
|
|
||||||
bdi->suppress_time = 0;
|
|
||||||
bdi->t_updated = t_now;
|
|
||||||
|
|
||||||
/* Need to announce UPDATE once this path is usable
|
|
||||||
* again. */
|
|
||||||
if (bdi->lastrecord == BGP_RECORD_UPDATE)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t_diff = t_now - bdi->t_updated;
|
|
||||||
bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty);
|
|
||||||
|
|
||||||
if (bdi->penalty <= damp->reuse_limit / 2.0) {
|
|
||||||
/* release the bdi, bdi->path. */
|
|
||||||
bgp_damp_info_free(bdi, 1);
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
bdi->t_updated = t_now;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
|
|
||||||
{
|
{
|
||||||
struct bgp_path_info *path;
|
struct bgp_path_info *path;
|
||||||
|
struct bgp_damp_config *bdc = &damp[afi][safi];
|
||||||
|
|
||||||
if (!bdi)
|
if (!bdi)
|
||||||
return;
|
return;
|
||||||
@ -344,9 +308,9 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
|
|||||||
path->extra->damp_info = NULL;
|
path->extra->damp_info = NULL;
|
||||||
|
|
||||||
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
|
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
|
||||||
bgp_reuse_list_delete(bdi);
|
bgp_reuse_list_delete(bdi, bdc);
|
||||||
else
|
else
|
||||||
BGP_DAMP_LIST_DEL(damp, bdi);
|
BGP_DAMP_LIST_DEL(bdc, bdi);
|
||||||
|
|
||||||
bgp_path_info_unset_flag(bdi->rn, path,
|
bgp_path_info_unset_flag(bdi->rn, path,
|
||||||
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
|
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
|
||||||
@ -357,68 +321,67 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw)
|
|||||||
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
|
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,
|
||||||
|
struct bgp_damp_config *bdc)
|
||||||
{
|
{
|
||||||
double reuse_max_ratio;
|
double reuse_max_ratio;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
double j;
|
double j;
|
||||||
|
|
||||||
damp->suppress_value = sup;
|
bdc->suppress_value = sup;
|
||||||
damp->half_life = hlife;
|
bdc->half_life = hlife;
|
||||||
damp->reuse_limit = reuse;
|
bdc->reuse_limit = reuse;
|
||||||
damp->max_suppress_time = maxsup;
|
bdc->max_suppress_time = maxsup;
|
||||||
|
|
||||||
/* Initialize params per bgp_damp_config. */
|
/* Initialize params per bgp_damp_config. */
|
||||||
damp->reuse_index_size = REUSE_ARRAY_SIZE;
|
bdc->reuse_index_size = REUSE_ARRAY_SIZE;
|
||||||
|
|
||||||
damp->ceiling =
|
bdc->ceiling = (int)(bdc->reuse_limit
|
||||||
(int)(damp->reuse_limit * (pow(2,
|
* (pow(2, (double)bdc->max_suppress_time
|
||||||
(double)damp->max_suppress_time
|
/ bdc->half_life)));
|
||||||
/ damp->half_life)));
|
|
||||||
|
|
||||||
/* Decay-array computations */
|
/* Decay-array computations */
|
||||||
damp->decay_array_size =
|
bdc->decay_array_size = ceil((double)bdc->max_suppress_time / DELTA_T);
|
||||||
ceil((double)damp->max_suppress_time / DELTA_T);
|
bdc->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY,
|
||||||
damp->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY,
|
sizeof(double) * (bdc->decay_array_size));
|
||||||
sizeof(double) * (damp->decay_array_size));
|
bdc->decay_array[0] = 1.0;
|
||||||
damp->decay_array[0] = 1.0;
|
bdc->decay_array[1] =
|
||||||
damp->decay_array[1] =
|
exp((1.0 / ((double)bdc->half_life / DELTA_T)) * log(0.5));
|
||||||
exp((1.0 / ((double)damp->half_life / DELTA_T)) * log(0.5));
|
|
||||||
|
|
||||||
/* Calculate decay values for all possible times */
|
/* Calculate decay values for all possible times */
|
||||||
for (i = 2; i < damp->decay_array_size; i++)
|
for (i = 2; i < bdc->decay_array_size; i++)
|
||||||
damp->decay_array[i] =
|
bdc->decay_array[i] =
|
||||||
damp->decay_array[i - 1] * damp->decay_array[1];
|
bdc->decay_array[i - 1] * bdc->decay_array[1];
|
||||||
|
|
||||||
/* Reuse-list computations */
|
/* Reuse-list computations */
|
||||||
i = ceil((double)damp->max_suppress_time / DELTA_REUSE) + 1;
|
i = ceil((double)bdc->max_suppress_time / DELTA_REUSE) + 1;
|
||||||
if (i > REUSE_LIST_SIZE || i == 0)
|
if (i > REUSE_LIST_SIZE || i == 0)
|
||||||
i = REUSE_LIST_SIZE;
|
i = REUSE_LIST_SIZE;
|
||||||
damp->reuse_list_size = i;
|
bdc->reuse_list_size = i;
|
||||||
|
|
||||||
damp->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
|
bdc->reuse_list =
|
||||||
damp->reuse_list_size
|
XCALLOC(MTYPE_BGP_DAMP_ARRAY,
|
||||||
* sizeof(struct bgp_reuse_node *));
|
bdc->reuse_list_size * sizeof(struct bgp_reuse_node *));
|
||||||
|
|
||||||
/* Reuse-array computations */
|
/* Reuse-array computations */
|
||||||
damp->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
|
bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
|
||||||
sizeof(int) * damp->reuse_index_size);
|
sizeof(int) * bdc->reuse_index_size);
|
||||||
|
|
||||||
reuse_max_ratio = (double)damp->ceiling / damp->reuse_limit;
|
reuse_max_ratio = (double)bdc->ceiling / bdc->reuse_limit;
|
||||||
j = (exp((double)damp->max_suppress_time / damp->half_life)
|
j = (exp((double)bdc->max_suppress_time / bdc->half_life) * log10(2.0));
|
||||||
* log10(2.0));
|
|
||||||
if (reuse_max_ratio > j && j != 0)
|
if (reuse_max_ratio > j && j != 0)
|
||||||
reuse_max_ratio = j;
|
reuse_max_ratio = j;
|
||||||
|
|
||||||
damp->scale_factor =
|
bdc->scale_factor =
|
||||||
(double)damp->reuse_index_size / (reuse_max_ratio - 1);
|
(double)bdc->reuse_index_size / (reuse_max_ratio - 1);
|
||||||
|
|
||||||
for (i = 0; i < damp->reuse_index_size; i++) {
|
for (i = 0; i < bdc->reuse_index_size; i++) {
|
||||||
damp->reuse_index[i] =
|
bdc->reuse_index[i] =
|
||||||
(int)(((double)damp->half_life / DELTA_REUSE)
|
(int)(((double)bdc->half_life / DELTA_REUSE)
|
||||||
* log10(1.0 / (damp->reuse_limit
|
* log10(1.0
|
||||||
* (1.0 + ((double)i
|
/ (bdc->reuse_limit
|
||||||
/ damp->scale_factor))))
|
* (1.0
|
||||||
|
+ ((double)i / bdc->scale_factor))))
|
||||||
/ log10(0.5));
|
/ log10(0.5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,122 +389,129 @@ 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 = &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 (damp->half_life == half && damp->reuse_limit == reuse
|
if (bdc->half_life == half && bdc->reuse_limit == reuse
|
||||||
&& damp->suppress_value == suppress
|
&& bdc->suppress_value == suppress
|
||||||
&& damp->max_suppress_time == max)
|
&& bdc->max_suppress_time == max)
|
||||||
return 0;
|
return 0;
|
||||||
bgp_damp_disable(bgp, afi, safi);
|
bgp_damp_disable(bgp, afi, safi);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
|
||||||
|
|
||||||
/* Register reuse timer. */
|
/* Register reuse timer. */
|
||||||
thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE,
|
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
|
||||||
&damp->t_reuse);
|
&bdc->t_reuse);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bgp_damp_config_clean(struct bgp_damp_config *damp)
|
static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
|
||||||
{
|
{
|
||||||
/* Free decay array */
|
/* Free decay array */
|
||||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array);
|
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array);
|
||||||
damp->decay_array_size = 0;
|
bdc->decay_array_size = 0;
|
||||||
|
|
||||||
/* Free reuse index array */
|
/* Free reuse index array */
|
||||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index);
|
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
|
||||||
damp->reuse_index_size = 0;
|
bdc->reuse_index_size = 0;
|
||||||
|
|
||||||
/* Free reuse list array. */
|
/* Free reuse list array. */
|
||||||
XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list);
|
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
|
||||||
damp->reuse_list_size = 0;
|
bdc->reuse_list_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean all the bgp_damp_info stored in reuse_list. */
|
/* Clean all the bgp_damp_info stored in reuse_list. */
|
||||||
void bgp_damp_info_clean(void)
|
void bgp_damp_info_clean(afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct bgp_damp_info *bdi, *next;
|
struct bgp_damp_info *bdi, *next;
|
||||||
|
struct bgp_damp_config *bdc = &damp[afi][safi];
|
||||||
|
|
||||||
damp->reuse_offset = 0;
|
bdc->reuse_offset = 0;
|
||||||
|
|
||||||
for (i = 0; i < damp->reuse_list_size; i++) {
|
for (i = 0; i < bdc->reuse_list_size; i++) {
|
||||||
if (!damp->reuse_list[i])
|
if (!bdc->reuse_list[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (bdi = damp->reuse_list[i]; bdi; bdi = next) {
|
for (bdi = bdc->reuse_list[i]; bdi; bdi = next) {
|
||||||
next = bdi->next;
|
next = bdi->next;
|
||||||
bgp_damp_info_free(bdi, 1);
|
bgp_damp_info_free(bdi, 1, afi, safi);
|
||||||
}
|
}
|
||||||
damp->reuse_list[i] = NULL;
|
bdc->reuse_list[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bdi = damp->no_reuse_list; bdi; bdi = next) {
|
for (bdi = bdc->no_reuse_list; bdi; bdi = next) {
|
||||||
next = bdi->next;
|
next = bdi->next;
|
||||||
bgp_damp_info_free(bdi, 1);
|
bgp_damp_info_free(bdi, 1, afi, safi);
|
||||||
}
|
}
|
||||||
damp->no_reuse_list = NULL;
|
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 = &damp[afi][safi];
|
||||||
/* 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 thread. */
|
/* Cancel reuse thread. */
|
||||||
if (damp->t_reuse)
|
if (bdc->t_reuse)
|
||||||
thread_cancel(damp->t_reuse);
|
thread_cancel(bdc->t_reuse);
|
||||||
damp->t_reuse = NULL;
|
bdc->t_reuse = NULL;
|
||||||
|
|
||||||
/* Clean BGP dampening information. */
|
/* Clean BGP dampening information. */
|
||||||
bgp_damp_info_clean();
|
bgp_damp_info_clean(afi, safi);
|
||||||
|
|
||||||
/* Clear configuration */
|
/* Clear configuration */
|
||||||
bgp_damp_config_clean(&bgp_damp_cfg);
|
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)
|
void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi)
|
||||||
{
|
{
|
||||||
if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE * 60
|
if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60
|
||||||
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
|
&& damp[afi][safi].reuse_limit == DEFAULT_REUSE
|
||||||
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
|
&& damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
|
||||||
&& bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life * 4)
|
&& damp[afi][safi].max_suppress_time
|
||||||
vty_out(vty, " bgp dampening\n");
|
== damp[afi][safi].half_life * 4)
|
||||||
else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE * 60
|
vty_out(vty, " bgp dampening\n");
|
||||||
&& bgp_damp_cfg.reuse_limit == DEFAULT_REUSE
|
else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60
|
||||||
&& bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS
|
&& damp[afi][safi].reuse_limit == DEFAULT_REUSE
|
||||||
&& bgp_damp_cfg.max_suppress_time
|
&& damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
|
||||||
== bgp_damp_cfg.half_life * 4)
|
&& damp[afi][safi].max_suppress_time
|
||||||
vty_out(vty, " bgp dampening %lld\n",
|
== damp[afi][safi].half_life * 4)
|
||||||
bgp_damp_cfg.half_life / 60LL);
|
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",
|
||||||
bgp_damp_cfg.half_life / 60LL, bgp_damp_cfg.reuse_limit,
|
damp[afi][safi].half_life / 60LL,
|
||||||
bgp_damp_cfg.suppress_value,
|
damp[afi][safi].reuse_limit,
|
||||||
bgp_damp_cfg.max_suppress_time / 60LL);
|
damp[afi][safi].suppress_value,
|
||||||
|
damp[afi][safi].max_suppress_time / 60LL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
|
static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
|
||||||
size_t len, bool use_json,
|
size_t len, afi_t afi, safi_t safi,
|
||||||
json_object *json)
|
bool use_json, json_object *json)
|
||||||
{
|
{
|
||||||
time_t reuse_time = 0;
|
time_t reuse_time = 0;
|
||||||
struct tm *tm = NULL;
|
struct tm *tm = NULL;
|
||||||
int time_store = 0;
|
int time_store = 0;
|
||||||
|
|
||||||
if (penalty > damp->reuse_limit) {
|
if (penalty > damp[afi][safi].reuse_limit) {
|
||||||
reuse_time = (int)(DELTA_T
|
reuse_time = (int)(DELTA_T
|
||||||
* ((log((double)damp->reuse_limit / penalty))
|
* ((log((double)damp[afi][safi].reuse_limit
|
||||||
/ (log(damp->decay_array[1]))));
|
/ penalty))
|
||||||
|
/ (log(damp[afi][safi].decay_array[1]))));
|
||||||
|
|
||||||
if (reuse_time > damp->max_suppress_time)
|
if (reuse_time > damp[afi][safi].max_suppress_time)
|
||||||
reuse_time = damp->max_suppress_time;
|
reuse_time = damp[afi][safi].max_suppress_time;
|
||||||
|
|
||||||
tm = gmtime(&reuse_time);
|
tm = gmtime(&reuse_time);
|
||||||
} else
|
} else
|
||||||
@ -593,13 +563,14 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
|
||||||
json_object *json_path)
|
safi_t safi, 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 = &damp[afi][safi];
|
||||||
|
|
||||||
if (!path->extra)
|
if (!path->extra)
|
||||||
return;
|
return;
|
||||||
@ -609,13 +580,13 @@ void bgp_damp_info_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 (!damp || !bdi)
|
if (!bdc || !bdi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Calculate new penalty. */
|
/* Calculate new penalty. */
|
||||||
t_now = bgp_clock();
|
t_now = bgp_clock();
|
||||||
t_diff = t_now - bdi->t_updated;
|
t_diff = t_now - bdi->t_updated;
|
||||||
penalty = bgp_damp_decay(t_diff, bdi->penalty);
|
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
|
||||||
|
|
||||||
if (json_path) {
|
if (json_path) {
|
||||||
json_object_int_add(json_path, "dampeningPenalty", penalty);
|
json_object_int_add(json_path, "dampeningPenalty", penalty);
|
||||||
@ -625,8 +596,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
|||||||
|
|
||||||
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(penalty, timebuf, BGP_UPTIME_LEN, 1,
|
bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN,
|
||||||
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",
|
||||||
@ -638,7 +609,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
|||||||
&& !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(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");
|
||||||
@ -646,12 +617,14 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, bool use_json,
|
char *timebuf, size_t len, afi_t afi,
|
||||||
|
safi_t safi, bool use_json,
|
||||||
json_object *json)
|
json_object *json)
|
||||||
{
|
{
|
||||||
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 = &damp[afi][safi];
|
||||||
|
|
||||||
if (!path->extra)
|
if (!path->extra)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -661,15 +634,16 @@ 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 (!damp || !bdi)
|
if (!bdc || !bdi)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Calculate new penalty. */
|
/* Calculate new penalty. */
|
||||||
t_now = bgp_clock();
|
t_now = bgp_clock();
|
||||||
t_diff = t_now - bdi->t_updated;
|
t_diff = t_now - bdi->t_updated;
|
||||||
penalty = bgp_damp_decay(t_diff, bdi->penalty);
|
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
|
||||||
|
|
||||||
return bgp_get_reuse_time(penalty, timebuf, len, use_json, json);
|
return bgp_get_reuse_time(penalty, timebuf, len, afi, safi, use_json,
|
||||||
|
json);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
|
int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
|
||||||
@ -684,12 +658,15 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi)
|
|||||||
|
|
||||||
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
|
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
|
||||||
vty_out(vty, "Half-life time: %lld min\n",
|
vty_out(vty, "Half-life time: %lld min\n",
|
||||||
(long long)damp->half_life / 60);
|
(long long)damp[afi][safi].half_life / 60);
|
||||||
vty_out(vty, "Reuse penalty: %d\n", damp->reuse_limit);
|
vty_out(vty, "Reuse penalty: %d\n",
|
||||||
vty_out(vty, "Suppress penalty: %d\n", damp->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)damp->max_suppress_time / 60);
|
(long long)damp[afi][safi].max_suppress_time / 60);
|
||||||
vty_out(vty, "Max suppress penalty: %u\n", damp->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",
|
||||||
|
@ -106,6 +106,9 @@ struct bgp_damp_config {
|
|||||||
|
|
||||||
/* Reuse timer thread per-set base. */
|
/* Reuse timer thread per-set base. */
|
||||||
struct thread *t_reuse;
|
struct thread *t_reuse;
|
||||||
|
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BGP_DAMP_NONE 0
|
#define BGP_DAMP_NONE 0
|
||||||
@ -134,17 +137,18 @@ extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn,
|
|||||||
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_node *rn,
|
extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn,
|
||||||
afi_t afi, safi_t saff);
|
afi_t afi, safi_t saff);
|
||||||
extern int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi);
|
extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw,
|
||||||
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(void);
|
extern void bgp_damp_info_clean(afi_t afi, safi_t safi);
|
||||||
extern int bgp_damp_decay(time_t, int);
|
extern int bgp_damp_decay(time_t, int, struct bgp_damp_config *damp);
|
||||||
extern void bgp_config_write_damp(struct vty *);
|
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,
|
extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
|
||||||
json_object *json_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,
|
char *timebuf, size_t len, afi_t afi,
|
||||||
bool use_json, json_object *json);
|
safi_t safi, bool use_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);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_DAMP_H */
|
#endif /* _QUAGGA_BGP_DAMP_H */
|
||||||
|
@ -196,7 +196,8 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
|
|||||||
|
|
||||||
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->safi);
|
||||||
|
|
||||||
e->damp_info = NULL;
|
e->damp_info = NULL;
|
||||||
if (e->parent) {
|
if (e->parent) {
|
||||||
@ -7886,7 +7887,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
|
|||||||
|
|
||||||
/* dampening route */
|
/* dampening route */
|
||||||
static void damp_route_vty_out(struct vty *vty, struct prefix *p,
|
static void damp_route_vty_out(struct vty *vty, struct prefix *p,
|
||||||
struct bgp_path_info *path, int display,
|
struct bgp_path_info *path, int display, afi_t afi,
|
||||||
safi_t safi, bool use_json, json_object *json)
|
safi_t safi, bool use_json, json_object *json)
|
||||||
{
|
{
|
||||||
struct attr *attr;
|
struct attr *attr;
|
||||||
@ -7917,13 +7918,13 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_json)
|
if (use_json)
|
||||||
bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN,
|
bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
|
||||||
use_json, json);
|
safi, use_json, json);
|
||||||
else
|
else
|
||||||
vty_out(vty, "%s ",
|
vty_out(vty, "%s ",
|
||||||
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
||||||
BGP_UPTIME_LEN, use_json,
|
BGP_UPTIME_LEN, afi, safi,
|
||||||
json));
|
use_json, json));
|
||||||
|
|
||||||
/* Print attribute */
|
/* Print attribute */
|
||||||
attr = path->attr;
|
attr = path->attr;
|
||||||
@ -7950,7 +7951,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p,
|
|||||||
|
|
||||||
/* flap route */
|
/* flap route */
|
||||||
static void flap_route_vty_out(struct vty *vty, struct prefix *p,
|
static void flap_route_vty_out(struct vty *vty, struct prefix *p,
|
||||||
struct bgp_path_info *path, int display,
|
struct bgp_path_info *path, int display, afi_t afi,
|
||||||
safi_t safi, bool use_json, json_object *json)
|
safi_t safi, bool use_json, json_object *json)
|
||||||
{
|
{
|
||||||
struct attr *attr;
|
struct attr *attr;
|
||||||
@ -8009,12 +8010,13 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p,
|
|||||||
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
|
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
|
||||||
if (use_json)
|
if (use_json)
|
||||||
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
||||||
BGP_UPTIME_LEN, use_json, json);
|
BGP_UPTIME_LEN, afi, safi,
|
||||||
|
use_json, json);
|
||||||
else
|
else
|
||||||
vty_out(vty, "%s ",
|
vty_out(vty, "%s ",
|
||||||
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
bgp_damp_reuse_time_vty(vty, path, timebuf,
|
||||||
BGP_UPTIME_LEN,
|
BGP_UPTIME_LEN, afi,
|
||||||
use_json, json));
|
safi, use_json, json));
|
||||||
} else {
|
} else {
|
||||||
if (!use_json)
|
if (!use_json)
|
||||||
vty_out(vty, "%*s ", 8, " ");
|
vty_out(vty, "%*s ", 8, " ");
|
||||||
@ -8943,7 +8945,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path->extra && path->extra->damp_info)
|
if (path->extra && path->extra->damp_info)
|
||||||
bgp_damp_info_vty(vty, path, 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])
|
||||||
@ -9370,11 +9372,11 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
|||||||
}
|
}
|
||||||
if (type == bgp_show_type_dampend_paths
|
if (type == bgp_show_type_dampend_paths
|
||||||
|| type == bgp_show_type_damp_neighbor)
|
|| type == bgp_show_type_damp_neighbor)
|
||||||
damp_route_vty_out(vty, &rn->p, pi, display,
|
damp_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
|
||||||
safi, use_json, json_paths);
|
safi, use_json, json_paths);
|
||||||
else if (type == bgp_show_type_flap_statistics
|
else if (type == bgp_show_type_flap_statistics
|
||||||
|| type == bgp_show_type_flap_neighbor)
|
|| type == bgp_show_type_flap_neighbor)
|
||||||
flap_route_vty_out(vty, &rn->p, pi, display,
|
flap_route_vty_out(vty, &rn->p, pi, display, AFI_IP,
|
||||||
safi, use_json, json_paths);
|
safi, use_json, json_paths);
|
||||||
else
|
else
|
||||||
route_vty_out(vty, &rn->p, pi, display, safi,
|
route_vty_out(vty, &rn->p, pi, display, safi,
|
||||||
@ -12206,7 +12208,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;
|
||||||
@ -12226,7 +12228,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;
|
||||||
@ -12248,7 +12250,7 @@ DEFUN (clear_ip_bgp_dampening,
|
|||||||
BGP_STR
|
BGP_STR
|
||||||
"Clear route flap dampening information\n")
|
"Clear route flap dampening information\n")
|
||||||
{
|
{
|
||||||
bgp_damp_info_clean();
|
bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
bgpd/bgpd.c
10
bgpd/bgpd.c
@ -7261,6 +7261,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
|
|||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* BGP flag dampening. */
|
||||||
|
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
|
BGP_CONFIG_DAMPENING))
|
||||||
|
bgp_config_write_damp(vty, afi, safi);
|
||||||
|
|
||||||
/* Route reflector client. */
|
/* Route reflector client. */
|
||||||
if (peergroup_af_flag_check(peer, afi, safi,
|
if (peergroup_af_flag_check(peer, afi, safi,
|
||||||
PEER_FLAG_REFLECTOR_CLIENT)) {
|
PEER_FLAG_REFLECTOR_CLIENT)) {
|
||||||
@ -7738,11 +7743,6 @@ int bgp_config_write(struct vty *vty)
|
|||||||
? ""
|
? ""
|
||||||
: "no ");
|
: "no ");
|
||||||
|
|
||||||
/* BGP flag dampening. */
|
|
||||||
if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
|
|
||||||
BGP_CONFIG_DAMPENING))
|
|
||||||
bgp_config_write_damp(vty);
|
|
||||||
|
|
||||||
/* BGP timers configuration. */
|
/* BGP timers configuration. */
|
||||||
if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
|
if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
|
||||||
&& bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
&& bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
|
||||||
|
Loading…
Reference in New Issue
Block a user