From 967d8257a9d081b6a8a98eadda7d087324ce77a3 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sun, 10 Nov 2019 20:13:20 +0200 Subject: [PATCH] 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 --- bgpd/bgp_damp.c | 385 ++++++++++++++++++++++------------------------- bgpd/bgp_damp.h | 20 ++- bgpd/bgp_route.c | 34 +++-- bgpd/bgpd.c | 10 +- 4 files changed, 216 insertions(+), 233 deletions(-) diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index cf085e46f..b0fee079d 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -37,8 +37,7 @@ #include "bgpd/bgp_advertise.h" /* Global variable to access damping configuration */ -struct bgp_damp_config bgp_damp_cfg; -static struct bgp_damp_config *damp = &bgp_damp_cfg; +static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX]; /* Utility macro to add and delete BGP dampening information to no 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) /* 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; int index; - i = (int)(((double)penalty / damp->reuse_limit - 1.0) - * damp->scale_factor); + i = (int)(((double)penalty / bdc->reuse_limit - 1.0) + * bdc->scale_factor); - if (i >= damp->reuse_index_size) - i = damp->reuse_index_size - 1; + if (i >= bdc->reuse_index_size) + 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. */ -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; - index = bdi->index = bgp_reuse_index(bdi->penalty); + index = bdi->index = bgp_reuse_index(bdi->penalty, bdc); bdi->prev = NULL; - bdi->next = damp->reuse_list[index]; - if (damp->reuse_list[index]) - damp->reuse_list[index]->prev = bdi; - damp->reuse_list[index] = bdi; + 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) +static void bgp_reuse_list_delete(struct bgp_damp_info *bdi, + struct bgp_damp_config *bdc) { if (bdi->next) bdi->next->prev = bdi->prev; if (bdi->prev) bdi->prev->next = bdi->next; else - damp->reuse_list[bdi->index] = bdi->next; + bdc->reuse_list[bdi->index] = bdi->next; } /* 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; @@ -97,10 +98,10 @@ int bgp_damp_decay(time_t tdiff, int penalty) if (i == 0) return penalty; - if (i >= damp->decay_array_size) + if (i >= bdc->decay_array_size) 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 @@ -111,20 +112,22 @@ static int bgp_reuse_timer(struct thread *t) struct bgp_damp_info *next; time_t t_now, t_diff; - damp->t_reuse = NULL; - thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, - &damp->t_reuse); + 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 zeroth queue head and zero the list head entry. */ - bdi = damp->reuse_list[damp->reuse_offset]; - damp->reuse_list[damp->reuse_offset] = NULL; + 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. */ - 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 ) */ 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 * [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. */ bdi->t_updated = t_now; /* if (figure-of-merit < reuse). */ - if (bdi->penalty < damp->reuse_limit) { + if (bdi->penalty < bdc->reuse_limit) { /* Reuse the route. */ bgp_path_info_unset_flag(bdi->rn, bdi->path, BGP_PATH_DAMPED); @@ -158,14 +161,14 @@ static int bgp_reuse_timer(struct thread *t) bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi); } - if (bdi->penalty <= damp->reuse_limit / 2.0) - bgp_damp_info_free(bdi, 1); + if (bdi->penalty <= bdc->reuse_limit / 2.0) + bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi); else - BGP_DAMP_LIST_ADD(damp, bdi); + BGP_DAMP_LIST_ADD(bdc, bdi); } else /* Re-insert into another list (See RFC2439 Section * 4.8.6). */ - bgp_reuse_list_add(bdi); + bgp_reuse_list_add(bdi, bdc); } return 0; @@ -178,6 +181,7 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn, time_t t_now; struct bgp_damp_info *bdi = NULL; unsigned int last_penalty = 0; + struct bgp_damp_config *bdc = &damp[afi][safi]; 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->safi = safi; (bgp_path_info_extra_get(path))->damp_info = bdi; - BGP_DAMP_LIST_ADD(damp, bdi); + BGP_DAMP_LIST_ADD(bdc, bdi); } else { last_penalty = bdi->penalty; /* 1. Set t-diff = t-now - t-updated. */ - bdi->penalty = - (bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty) - + (attr_change ? DEFAULT_PENALTY / 2 - : DEFAULT_PENALTY)); + bdi->penalty = (bgp_damp_decay(t_now - bdi->t_updated, + bdi->penalty, bdc) + + (attr_change ? DEFAULT_PENALTY / 2 + : DEFAULT_PENALTY)); - if (bdi->penalty > damp->ceiling) - bdi->penalty = damp->ceiling; + if (bdi->penalty > bdc->ceiling) + bdi->penalty = bdc->ceiling; 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 decay rate isn't equal to 0, reinsert brn. */ if (bdi->penalty != last_penalty && bdi->index >= 0) { - bgp_reuse_list_delete(bdi); - bgp_reuse_list_add(bdi); + bgp_reuse_list_delete(bdi, bdc); + bgp_reuse_list_add(bdi, bdc); } return BGP_DAMP_SUPPRESSED; } /* If not suppressed before, do annonunce this withdraw and 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); bdi->suppress_time = t_now; - BGP_DAMP_LIST_DEL(damp, bdi); - bgp_reuse_list_add(bdi); + BGP_DAMP_LIST_DEL(bdc, bdi); + bgp_reuse_list_add(bdi, bdc); } 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; struct bgp_damp_info *bdi; int status; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!path->extra || !((bdi = path->extra->damp_info))) 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); 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) - && (bdi->penalty < damp->suppress_value)) + && (bdi->penalty < bdc->suppress_value)) status = BGP_DAMP_USED; 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_reuse_list_delete(bdi); - BGP_DAMP_LIST_ADD(damp, bdi); + bgp_reuse_list_delete(bdi, bdc); + BGP_DAMP_LIST_ADD(bdc, bdi); bdi->suppress_time = 0; status = BGP_DAMP_USED; } else 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; else - bgp_damp_info_free(bdi, 0); + bgp_damp_info_free(bdi, 0, afi, safi); return status; } -/* Remove dampening information and history route. */ -int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, 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) +void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi, + safi_t safi) { struct bgp_path_info *path; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!bdi) return; @@ -344,9 +308,9 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw) path->extra->damp_info = NULL; if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) - bgp_reuse_list_delete(bdi); + bgp_reuse_list_delete(bdi, bdc); else - BGP_DAMP_LIST_DEL(damp, bdi); + BGP_DAMP_LIST_DEL(bdc, bdi); bgp_path_info_unset_flag(bdi->rn, path, 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); } -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; unsigned int i; double j; - damp->suppress_value = sup; - damp->half_life = hlife; - damp->reuse_limit = reuse; - damp->max_suppress_time = maxsup; + bdc->suppress_value = sup; + bdc->half_life = hlife; + bdc->reuse_limit = reuse; + bdc->max_suppress_time = maxsup; /* Initialize params per bgp_damp_config. */ - damp->reuse_index_size = REUSE_ARRAY_SIZE; + bdc->reuse_index_size = REUSE_ARRAY_SIZE; - damp->ceiling = - (int)(damp->reuse_limit * (pow(2, - (double)damp->max_suppress_time - / damp->half_life))); + bdc->ceiling = (int)(bdc->reuse_limit + * (pow(2, (double)bdc->max_suppress_time + / bdc->half_life))); /* Decay-array computations */ - damp->decay_array_size = - ceil((double)damp->max_suppress_time / DELTA_T); - damp->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY, - sizeof(double) * (damp->decay_array_size)); - damp->decay_array[0] = 1.0; - damp->decay_array[1] = - exp((1.0 / ((double)damp->half_life / DELTA_T)) * log(0.5)); + bdc->decay_array_size = ceil((double)bdc->max_suppress_time / DELTA_T); + bdc->decay_array = XMALLOC(MTYPE_BGP_DAMP_ARRAY, + sizeof(double) * (bdc->decay_array_size)); + bdc->decay_array[0] = 1.0; + bdc->decay_array[1] = + exp((1.0 / ((double)bdc->half_life / DELTA_T)) * log(0.5)); /* Calculate decay values for all possible times */ - for (i = 2; i < damp->decay_array_size; i++) - damp->decay_array[i] = - damp->decay_array[i - 1] * damp->decay_array[1]; + for (i = 2; i < bdc->decay_array_size; i++) + bdc->decay_array[i] = + bdc->decay_array[i - 1] * bdc->decay_array[1]; /* 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) i = REUSE_LIST_SIZE; - damp->reuse_list_size = i; + bdc->reuse_list_size = i; - damp->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY, - damp->reuse_list_size - * sizeof(struct bgp_reuse_node *)); + bdc->reuse_list = + XCALLOC(MTYPE_BGP_DAMP_ARRAY, + bdc->reuse_list_size * sizeof(struct bgp_reuse_node *)); /* Reuse-array computations */ - damp->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY, - sizeof(int) * damp->reuse_index_size); + bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY, + sizeof(int) * bdc->reuse_index_size); - reuse_max_ratio = (double)damp->ceiling / damp->reuse_limit; - j = (exp((double)damp->max_suppress_time / damp->half_life) - * log10(2.0)); + reuse_max_ratio = (double)bdc->ceiling / bdc->reuse_limit; + j = (exp((double)bdc->max_suppress_time / bdc->half_life) * log10(2.0)); if (reuse_max_ratio > j && j != 0) reuse_max_ratio = j; - damp->scale_factor = - (double)damp->reuse_index_size / (reuse_max_ratio - 1); + bdc->scale_factor = + (double)bdc->reuse_index_size / (reuse_max_ratio - 1); - for (i = 0; i < damp->reuse_index_size; i++) { - damp->reuse_index[i] = - (int)(((double)damp->half_life / DELTA_REUSE) - * log10(1.0 / (damp->reuse_limit - * (1.0 + ((double)i - / damp->scale_factor)))) + for (i = 0; i < bdc->reuse_index_size; i++) { + bdc->reuse_index[i] = + (int)(((double)bdc->half_life / DELTA_REUSE) + * log10(1.0 + / (bdc->reuse_limit + * (1.0 + + ((double)i / bdc->scale_factor)))) / 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, 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 (damp->half_life == half && damp->reuse_limit == reuse - && damp->suppress_value == suppress - && damp->max_suppress_time == max) + if (bdc->half_life == half && bdc->reuse_limit == reuse + && bdc->suppress_value == suppress + && bdc->max_suppress_time == max) return 0; bgp_damp_disable(bgp, afi, safi); } 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. */ - thread_add_timer(bm->master, bgp_reuse_timer, NULL, DELTA_REUSE, - &damp->t_reuse); + thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE, + &bdc->t_reuse); 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 */ - XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array); - damp->decay_array_size = 0; + XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array); + bdc->decay_array_size = 0; /* Free reuse index array */ - XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index); - damp->reuse_index_size = 0; + XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index); + bdc->reuse_index_size = 0; /* Free reuse list array. */ - XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list); - damp->reuse_list_size = 0; + XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list); + bdc->reuse_list_size = 0; } /* 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; 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++) { - if (!damp->reuse_list[i]) + for (i = 0; i < bdc->reuse_list_size; i++) { + if (!bdc->reuse_list[i]) continue; - for (bdi = damp->reuse_list[i]; bdi; bdi = next) { + for (bdi = bdc->reuse_list[i]; bdi; 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; - 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) { + 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 thread. */ - if (damp->t_reuse) - thread_cancel(damp->t_reuse); - damp->t_reuse = NULL; + if (bdc->t_reuse) + thread_cancel(bdc->t_reuse); + bdc->t_reuse = NULL; /* Clean BGP dampening information. */ - bgp_damp_info_clean(); + bgp_damp_info_clean(afi, safi); /* Clear configuration */ - bgp_damp_config_clean(&bgp_damp_cfg); + 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) +void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi) { - if (bgp_damp_cfg.half_life == DEFAULT_HALF_LIFE * 60 - && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE - && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS - && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life * 4) - vty_out(vty, " bgp dampening\n"); - else if (bgp_damp_cfg.half_life != DEFAULT_HALF_LIFE * 60 - && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE - && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS - && bgp_damp_cfg.max_suppress_time - == bgp_damp_cfg.half_life * 4) - vty_out(vty, " bgp dampening %lld\n", - bgp_damp_cfg.half_life / 60LL); + 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 (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", - bgp_damp_cfg.half_life / 60LL, bgp_damp_cfg.reuse_limit, - bgp_damp_cfg.suppress_value, - bgp_damp_cfg.max_suppress_time / 60LL); + vty_out(vty, " bgp dampening %lld %d %d %lld\n", + 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(unsigned int penalty, char *buf, - size_t len, bool use_json, - json_object *json) + size_t len, afi_t afi, safi_t safi, + bool use_json, json_object *json) { time_t reuse_time = 0; struct tm *tm = NULL; int time_store = 0; - if (penalty > damp->reuse_limit) { + if (penalty > damp[afi][safi].reuse_limit) { reuse_time = (int)(DELTA_T - * ((log((double)damp->reuse_limit / penalty)) - / (log(damp->decay_array[1])))); + * ((log((double)damp[afi][safi].reuse_limit + / penalty)) + / (log(damp[afi][safi].decay_array[1])))); - if (reuse_time > damp->max_suppress_time) - reuse_time = damp->max_suppress_time; + if (reuse_time > damp[afi][safi].max_suppress_time) + reuse_time = damp[afi][safi].max_suppress_time; tm = gmtime(&reuse_time); } else @@ -593,13 +563,14 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf, return buf; } -void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, - 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 = &damp[afi][safi]; if (!path->extra) 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, return immediately. */ - if (!damp || !bdi) + if (!bdc || !bdi) return; /* Calculate new penalty. */ t_now = bgp_clock(); 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) { 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) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) - bgp_get_reuse_time(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", @@ -638,7 +609,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, ", reuse in %s", bgp_get_reuse_time(penalty, timebuf, - BGP_UPTIME_LEN, 0, + BGP_UPTIME_LEN, afi, safi, 0, json_path)); 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, - 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) { struct bgp_damp_info *bdi; time_t t_now, t_diff; int penalty; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!path->extra) 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, return immediately. */ - if (!damp || !bdi) + if (!bdc || !bdi) return NULL; /* Calculate new penalty. */ t_now = bgp_clock(); 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) @@ -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)) { vty_out(vty, "Half-life time: %lld min\n", - (long long)damp->half_life / 60); - vty_out(vty, "Reuse penalty: %d\n", damp->reuse_limit); - vty_out(vty, "Suppress penalty: %d\n", damp->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)damp->max_suppress_time / 60); - vty_out(vty, "Max suppress penalty: %u\n", damp->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", diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index 18bf561c4..3dd860a29 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -106,6 +106,9 @@ struct bgp_damp_config { /* Reuse timer thread per-set base. */ struct thread *t_reuse; + + afi_t afi; + safi_t safi; }; #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); extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, 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_clean(void); -extern int bgp_damp_decay(time_t, int); -extern void bgp_config_write_damp(struct vty *); +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 *, afi_t afi, safi_t safi); 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, struct bgp_path_info *path, - char *timebuf, size_t len, - bool use_json, json_object *json); + char *timebuf, size_t len, afi_t afi, + safi_t safi, bool use_json, + json_object *json); extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t); #endif /* _QUAGGA_BGP_DAMP_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ee5f41d16..9d5348f07 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -189,7 +189,8 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) e = *extra; 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; if (e->parent) { @@ -7644,7 +7645,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, /* dampening route */ 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) { struct attr *attr; @@ -7675,13 +7676,13 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, } if (use_json) - bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, - use_json, json); + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, + safi, use_json, json); else vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, use_json, - json)); + BGP_UPTIME_LEN, afi, safi, + use_json, json)); /* Print attribute */ attr = path->attr; @@ -7708,7 +7709,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, /* flap route */ 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) { struct attr *attr; @@ -7767,12 +7768,13 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p, && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { if (use_json) bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, use_json, json); + BGP_UPTIME_LEN, afi, safi, + use_json, json); else vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, - use_json, json)); + BGP_UPTIME_LEN, afi, + safi, use_json, json)); } else { if (!use_json) vty_out(vty, "%*s ", 8, " "); @@ -8612,7 +8614,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } 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 */ if (path->extra && bgp_is_valid_label(&path->extra->label[0]) @@ -9022,11 +9024,11 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, } if (type == bgp_show_type_dampend_paths || 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); else if (type == bgp_show_type_flap_statistics || 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); else route_vty_out(vty, &rn->p, pi, display, safi, @@ -11896,7 +11898,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; @@ -11916,7 +11918,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; @@ -11938,7 +11940,7 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - bgp_damp_info_clean(); + bgp_damp_info_clean(AFI_IP, SAFI_UNICAST); return CMD_SUCCESS; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 66c1e623a..f0130c976 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7265,6 +7265,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, 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. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) { @@ -7804,11 +7809,6 @@ int bgp_config_write(struct vty *vty) ? "" : "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. */ if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME) -- 2.39.2