diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 48807dd657..6726dd6160 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -37,115 +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) -{ - struct reuselist_node *new_node; +/* Global variable to access damping configuration */ +static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX]; - assert(info); - new_node = XCALLOC(MTYPE_BGP_DAMP_REUSELIST, sizeof(*new_node)); - new_node->info = info; - SLIST_INSERT_HEAD(list, new_node, entry); -} - -static void bgp_reuselist_del(struct reuselist *list, - struct reuselist_node **node) -{ - if ((*node) == NULL) - return; - assert(list && node && *node); - SLIST_REMOVE(list, (*node), reuselist_node, entry); - XFREE(MTYPE_BGP_DAMP_REUSELIST, (*node)); - *node = NULL; -} - -static void bgp_reuselist_switch(struct reuselist *source, - struct reuselist_node *node, - struct reuselist *target) -{ - assert(source && target && node); - SLIST_REMOVE(source, node, reuselist_node, entry); - SLIST_INSERT_HEAD(target, node, entry); -} - -static void bgp_reuselist_free(struct reuselist *list) -{ - struct reuselist_node *rn; - - assert(list); - while ((rn = SLIST_FIRST(list)) != NULL) - bgp_reuselist_del(list, &rn); -} - -static struct reuselist_node *bgp_reuselist_find(struct reuselist *list, - struct bgp_damp_info *info) -{ - struct reuselist_node *rn; - - assert(list && info); - SLIST_FOREACH (rn, list, entry) { - if (rn->info == info) - return rn; - } - return NULL; -} - -static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi) -{ - struct reuselist_node *node; - - assert(bdi && bdi->config); - if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX) { - node = bgp_reuselist_find(&bdi->config->no_reuse_list, bdi); - if (node) - bgp_reuselist_del(&bdi->config->no_reuse_list, &node); - } else { - node = bgp_reuselist_find(&bdi->config->reuse_list[bdi->index], - bdi); - if (node) - bgp_reuselist_del(&bdi->config->reuse_list[bdi->index], - &node); - } - 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 @@ -168,45 +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, struct bgp_damp_config *bdc) { - struct reuselist *list; - struct reuselist_node *rn; - - list = &bdc->reuse_list[bdi->index]; - rn = bgp_reuselist_find(list, bdi); - bgp_damp_info_unclaim(bdi); - bgp_reuselist_del(list, &rn); -} - -static void bgp_no_reuse_list_add(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, - struct bgp_damp_config *bdc) -{ - struct reuselist_node *rn; - - assert(bdc && bdi); - if (bdi->config == NULL) { - bgp_damp_info_unclaim(bdi); - return; - } - bdi->config = NULL; - rn = bgp_reuselist_find(&bdc->no_reuse_list, bdi); - bgp_reuselist_del(&bdc->no_reuse_list, &rn); + 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. */ @@ -229,34 +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 reuselist_node *node; - 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]; - node = SLIST_FIRST(&plist); - 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 ((node = SLIST_FIRST(&plist)) != NULL) { - bdi = node->info; - 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; @@ -285,27 +169,16 @@ static int bgp_reuse_timer(struct thread *t) bdi->safi); } - if (bdi->penalty <= bdc->reuse_limit / 2.0) { - bgp_damp_info_free(&bdi, bdc, 1, bdi->afi, - bdi->safi); - bgp_reuselist_del(&plist, &node); - } else { - node->info->index = - BGP_DAMP_NO_REUSE_LIST_INDEX; - bgp_reuselist_switch(&plist, node, - &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, node, - &bdc->reuse_list[bdi->index]); - } + bgp_reuse_list_add(bdi, bdc); } - assert(SLIST_EMPTY(&plist)); - return 0; } @@ -316,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; @@ -344,13 +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 { - bgp_damp_info_claim(bdi, bdc); last_penalty = bdi->penalty; /* 1. Set t-diff = t-now - t-updated. */ @@ -376,7 +245,7 @@ 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) { + if (bdi->penalty != last_penalty && bdi->index >= 0) { bgp_reuse_list_delete(bdi, bdc); bgp_reuse_list_add(bdi, bdc); } @@ -388,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, bdc); + BGP_DAMP_LIST_DEL(bdc, bdi); bgp_reuse_list_add(bdi, bdc); } + return BGP_DAMP_USED; } @@ -400,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; @@ -422,7 +289,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, && (bdi->penalty < bdc->reuse_limit)) { bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED); bgp_reuse_list_delete(bdi, bdc); - bgp_no_reuse_list_add(bdi, bdc); + BGP_DAMP_LIST_ADD(bdc, bdi); bdi->suppress_time = 0; status = BGP_DAMP_USED; } else @@ -430,29 +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, bdc, 0, afi, safi); - } + else + bgp_damp_info_free(bdi, 0, afi, safi); return status; } -void bgp_damp_info_free(struct bgp_damp_info **bdi, struct bgp_damp_config *bdc, - int withdraw, afi_t afi, safi_t safi) +void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi, + safi_t safi) { - assert(bdc && bdi && *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); + + if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) + 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, @@ -495,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); @@ -522,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 @@ -534,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, @@ -544,30 +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_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_node *rn; - 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 ((rn = SLIST_FIRST(list)) != NULL) { - bdi = rn->info; - bgp_reuselist_del(list, &rn); - bgp_damp_info_free(&bdi, bdc, 1, afi, safi); - } - } - - while ((rn = SLIST_FIRST(&bdc->no_reuse_list)) != NULL) { - bdi = rn->info; - bgp_reuselist_del(&bdc->no_reuse_list, &rn); - bgp_damp_info_free(&bdi, bdc, 1, afi, safi); - } - /* Free decay array */ XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array); bdc->decay_array_size = 0; @@ -577,81 +428,96 @@ void bgp_damp_info_clean(struct bgp_damp_config *bdc, afi_t afi, safi_t safi) bdc->reuse_index_size = 0; /* Free reuse list array. */ - for (i = 0; i < bdc->reuse_list_size; ++i) - bgp_reuselist_free(&bdc->reuse_list[i]); - 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(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 @@ -703,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; @@ -737,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", @@ -749,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, @@ -766,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; @@ -788,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", @@ -817,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; @@ -857,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(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); - } -} diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index 1e0f249a47..0c70abef84 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -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; @@ -63,13 +63,6 @@ struct bgp_damp_info { safi_t safi; }; -struct reuselist_node { - SLIST_ENTRY(reuselist_node) entry; - struct bgp_damp_info *info; -}; - -SLIST_HEAD(reuselist, reuselist_node); - /* Specified parameter set configuration. */ struct bgp_damp_config { /* Value over which routes suppressed. */ @@ -107,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; @@ -139,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); @@ -148,18 +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 **path, - struct bgp_damp_config *bdc, 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(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_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, @@ -167,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 */ diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 196e56a937..ffb1ec162b 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -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"); diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index 0021fa9c3d..63e7b40ef7 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -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); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0c48d0d0bf..9acfd32b48 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -221,6 +221,9 @@ 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->afi, + e->damp_info->safi); e->damp_info = NULL; if (e->parent) { @@ -3391,16 +3394,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) { @@ -3848,7 +3849,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)) { @@ -3942,11 +3944,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); } @@ -4069,7 +4071,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); @@ -10573,7 +10575,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]) @@ -14758,8 +14760,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; bgp_damp_info_free( - &pi->extra->damp_info, - &bgp->damp[afi][safi], + pi->extra->damp_info, 1, afi, safi); pi = pi_temp; } else @@ -14781,8 +14782,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; bgp_damp_info_free( - &pi->extra->damp_info, - &bgp->damp[afi][safi], + pi->extra->damp_info, 1, afi, safi); pi = pi_temp; } else @@ -14805,9 +14805,7 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP, - SAFI_UNICAST); + bgp_damp_info_clean(AFI_IP, SAFI_UNICAST); return CMD_SUCCESS; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 6f9be93757..e64547f0d8 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2408,14 +2408,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) { @@ -3599,11 +3591,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"); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e6a828a2c0..867062a88b 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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 force */ -#define PEER_FLAG_CONFIG_DAMPENING (1U << 29) /* route flap dampening */ - enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];