diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index dd9de5dc99..6726dd6160 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -37,76 +37,19 @@ #include "bgpd/bgp_advertise.h" #include "bgpd/bgp_vty.h" -static void bgp_reuselist_add(struct reuselist *list, - struct bgp_damp_info *info) -{ - assert(info); - SLIST_INSERT_HEAD(list, info, entry); -} +/* Global variable to access damping configuration */ +static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX]; -static void bgp_reuselist_del(struct reuselist *list, - struct bgp_damp_info *info) -{ - assert(info); - SLIST_REMOVE(list, info, bgp_damp_info, entry); -} - -static void bgp_reuselist_switch(struct reuselist *source, - struct bgp_damp_info *info, - struct reuselist *target) -{ - assert(source && target && info); - SLIST_REMOVE(source, info, bgp_damp_info, entry); - SLIST_INSERT_HEAD(target, info, entry); -} - -static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi) -{ - assert(bdi && bdi->config); - if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX) - bgp_reuselist_del(&bdi->config->no_reuse_list, bdi); - else - bgp_reuselist_del(&bdi->config->reuse_list[bdi->index], bdi); - bdi->config = NULL; -} - -static void bgp_damp_info_claim(struct bgp_damp_info *bdi, - struct bgp_damp_config *bdc) -{ - assert(bdc && bdi); - if (bdi->config == NULL) { - bdi->config = bdc; - return; - } - bgp_damp_info_unclaim(bdi); - bdi->config = bdc; - bdi->afi = bdc->afi; - bdi->safi = bdc->safi; -} - -struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi, - afi_t afi, safi_t safi) -{ - if (!pi) - return NULL; - if (CHECK_FLAG(pi->peer->af_flags[afi][safi], - PEER_FLAG_CONFIG_DAMPENING)) - return &pi->peer->damp[afi][safi]; - if (peer_group_active(pi->peer)) - if (CHECK_FLAG(pi->peer->group->conf->af_flags[afi][safi], - PEER_FLAG_CONFIG_DAMPENING)) - return &pi->peer->group->conf->damp[afi][safi]; - if (CHECK_FLAG(pi->peer->bgp->af_flags[afi][safi], - BGP_CONFIG_DAMPENING)) - return &pi->peer->bgp->damp[afi][safi]; - return NULL; -} +/* Utility macro to add and delete BGP dampening information to no + used list. */ +#define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list) +#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list) /* Calculate reuse list index by penalty value. */ static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc) { unsigned int i; - unsigned int index; + int index; /* * reuse_limit can't be zero, this is for Coverity @@ -129,28 +72,27 @@ static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc) static void bgp_reuse_list_add(struct bgp_damp_info *bdi, struct bgp_damp_config *bdc) { - bgp_damp_info_claim(bdi, bdc); - bdi->index = bgp_reuse_index(bdi->penalty, bdc); - bgp_reuselist_add(&bdc->reuse_list[bdi->index], bdi); + int index; + + index = bdi->index = bgp_reuse_index(bdi->penalty, bdc); + + bdi->prev = NULL; + bdi->next = bdc->reuse_list[index]; + if (bdc->reuse_list[index]) + bdc->reuse_list[index]->prev = bdi; + bdc->reuse_list[index] = bdi; } /* Delete BGP dampening information from reuse list. */ -static void bgp_reuse_list_delete(struct bgp_damp_info *bdi) -{ - bgp_damp_info_unclaim(bdi); -} - -static void bgp_no_reuse_list_add(struct bgp_damp_info *bdi, +static void bgp_reuse_list_delete(struct bgp_damp_info *bdi, struct bgp_damp_config *bdc) { - bgp_damp_info_claim(bdi, bdc); - bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; - bgp_reuselist_add(&bdc->no_reuse_list, bdi); -} - -static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi) -{ - bgp_damp_info_unclaim(bdi); + if (bdi->next) + bdi->next->prev = bdi->prev; + if (bdi->prev) + bdi->prev->next = bdi->next; + else + bdc->reuse_list[bdi->index] = bdi->next; } /* Return decayed penalty value. */ @@ -173,31 +115,32 @@ int bgp_damp_decay(time_t tdiff, int penalty, struct bgp_damp_config *bdc) is evaluated. RFC2439 Section 4.8.7. */ static int bgp_reuse_timer(struct thread *t) { - struct bgp_damp_config *bdc = THREAD_ARG(t); struct bgp_damp_info *bdi; - struct reuselist plist; - struct bgp *bgp; + struct bgp_damp_info *next; time_t t_now, t_diff; + struct bgp_damp_config *bdc = THREAD_ARG(t); + + bdc->t_reuse = NULL; thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE, &bdc->t_reuse); t_now = bgp_clock(); - /* 1. save a pointer to the current queue head and zero the list head - * list head entry. */ - assert(bdc->reuse_offset < bdc->reuse_list_size); - plist = bdc->reuse_list[bdc->reuse_offset]; - SLIST_INIT(&bdc->reuse_list[bdc->reuse_offset]); + /* 1. save a pointer to the current zeroth queue head and zero the + list head entry. */ + bdi = bdc->reuse_list[bdc->reuse_offset]; + bdc->reuse_list[bdc->reuse_offset] = NULL; /* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby rotating the circular queue of list-heads. */ bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size; - assert(bdc->reuse_offset < bdc->reuse_list_size); /* 3. if ( the saved list head pointer is non-empty ) */ - while ((bdi = SLIST_FIRST(&plist)) != NULL) { - bgp = bdi->path->peer->bgp; + for (; bdi; bdi = next) { + struct bgp *bgp = bdi->path->peer->bgp; + + next = bdi->next; /* Set t-diff = t-now - t-updated. */ t_diff = t_now - bdi->t_updated; @@ -226,25 +169,16 @@ static int bgp_reuse_timer(struct thread *t) bdi->safi); } - if (bdi->penalty <= bdc->reuse_limit / 2.0) { - bgp_reuselist_del(&plist, bdi); - bgp_damp_info_free(bdi, 1); - } else { - bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; - bgp_reuselist_switch(&plist, bdi, - &bdc->no_reuse_list); - } - } else { + if (bdi->penalty <= bdc->reuse_limit / 2.0) + bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi); + else + BGP_DAMP_LIST_ADD(bdc, bdi); + } else /* Re-insert into another list (See RFC2439 Section * 4.8.6). */ - bdi->index = bgp_reuse_index(bdi->penalty, bdc); - bgp_reuselist_switch(&plist, bdi, - &bdc->reuse_list[bdi->index]); - } + bgp_reuse_list_add(bdi, bdc); } - assert(SLIST_EMPTY(&plist)); - return 0; } @@ -255,13 +189,10 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest, time_t t_now; struct bgp_damp_info *bdi = NULL; unsigned int last_penalty = 0; - struct bgp_damp_config *bdc; - - bdc = get_active_bdc_from_pi(path, afi, safi); - if (!bdc) - return BGP_DAMP_USED; + struct bgp_damp_config *bdc = &damp[afi][safi]; t_now = bgp_clock(); + /* Processing Unreachable Messages. */ if (path->extra) bdi = path->extra->damp_info; @@ -283,20 +214,12 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest, bdi->flap = 1; bdi->start_time = t_now; bdi->suppress_time = 0; - bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX; + bdi->index = -1; bdi->afi = afi; bdi->safi = safi; (bgp_path_info_extra_get(path))->damp_info = bdi; - bgp_no_reuse_list_add(bdi, bdc); + BGP_DAMP_LIST_ADD(bdc, bdi); } else { - if (bdi->config != bdc) { - bgp_damp_info_claim(bdi, bdc); - if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX) - bgp_reuselist_add(&bdc->no_reuse_list, bdi); - else - bgp_reuselist_add(&bdc->reuse_list[bdi->index], - bdi); - } last_penalty = bdi->penalty; /* 1. Set t-diff = t-now - t-updated. */ @@ -322,8 +245,8 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest, /* Remove the route from a reuse list if it is on one. */ if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) { /* If decay rate isn't equal to 0, reinsert brn. */ - if (bdi->penalty != last_penalty) { - bgp_reuse_list_delete(bdi); + if (bdi->penalty != last_penalty && bdi->index >= 0) { + bgp_reuse_list_delete(bdi, bdc); bgp_reuse_list_add(bdi, bdc); } return BGP_DAMP_SUPPRESSED; @@ -334,9 +257,10 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest, if (bdi->penalty >= bdc->suppress_value) { bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED); bdi->suppress_time = t_now; - bgp_no_reuse_list_delete(bdi); + BGP_DAMP_LIST_DEL(bdc, bdi); bgp_reuse_list_add(bdi, bdc); } + return BGP_DAMP_USED; } @@ -346,10 +270,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, time_t t_now; struct bgp_damp_info *bdi; int status; - struct bgp_damp_config *bdc; - - bdc = get_active_bdc_from_pi(path, afi, safi); - assert(bdc); + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!path->extra || !((bdi = path->extra->damp_info))) return BGP_DAMP_USED; @@ -367,8 +288,8 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED) && (bdi->penalty < bdc->reuse_limit)) { bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED); - bgp_reuse_list_delete(bdi); - bgp_no_reuse_list_add(bdi, bdc); + bgp_reuse_list_delete(bdi, bdc); + BGP_DAMP_LIST_ADD(bdc, bdi); bdi->suppress_time = 0; status = BGP_DAMP_USED; } else @@ -376,28 +297,36 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, if (bdi->penalty > bdc->reuse_limit / 2.0) bdi->t_updated = t_now; - else { - bgp_damp_info_unclaim(bdi); - bgp_damp_info_free(bdi, 0); - } + else + bgp_damp_info_free(bdi, 0, afi, safi); return status; } -void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw) +void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi, + safi_t safi) { - assert(bdi); + struct bgp_path_info *path; + struct bgp_damp_config *bdc = &damp[afi][safi]; - if (bdi->path == NULL) { - XFREE(MTYPE_BGP_DAMP_INFO, bdi); + if (!bdi) return; - } - bdi->path->extra->damp_info = NULL; - bgp_path_info_unset_flag(bdi->dest, bdi->path, + path = bdi->path; + path->extra->damp_info = NULL; + + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) + bgp_reuse_list_delete(bdi, bdc); + else + BGP_DAMP_LIST_DEL(bdc, bdi); + + bgp_path_info_unset_flag(bdi->dest, path, BGP_PATH_HISTORY | BGP_PATH_DAMPED); + if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) - bgp_path_info_delete(bdi->dest, bdi->path); + bgp_path_info_delete(bdi->dest, path); + + XFREE(MTYPE_BGP_DAMP_INFO, bdi); } static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup, @@ -440,7 +369,8 @@ static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup, bdc->reuse_list = XCALLOC(MTYPE_BGP_DAMP_ARRAY, - bdc->reuse_list_size * sizeof(struct reuselist)); + bdc->reuse_list_size * sizeof(struct bgp_reuse_node *)); + /* Reuse-array computations */ bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY, sizeof(int) * bdc->reuse_index_size); @@ -467,7 +397,7 @@ static void bgp_damp_parameter_set(int hlife, int reuse, int sup, int maxsup, int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half, unsigned int reuse, unsigned int suppress, time_t max) { - struct bgp_damp_config *bdc = &bgp->damp[afi][safi]; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) { if (bdc->half_life == half && bdc->reuse_limit == reuse @@ -479,8 +409,6 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half, SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); bgp_damp_parameter_set(half, reuse, suppress, max, bdc); - bdc->afi = afi; - bdc->safi = safi; /* Register reuse timer. */ thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE, @@ -489,35 +417,8 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half, return 0; } -/* Clean all the bgp_damp_info stored in reuse_list and no_reuse_list. */ -void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc, - afi_t afi, safi_t safi) +static void bgp_damp_config_clean(struct bgp_damp_config *bdc) { - struct bgp_damp_info *bdi; - struct reuselist *list; - unsigned int i; - - bdc->reuse_offset = 0; - for (i = 0; i < bdc->reuse_list_size; ++i) { - list = &bdc->reuse_list[i]; - while ((bdi = SLIST_FIRST(list)) != NULL) { - if (bdi->lastrecord == BGP_RECORD_UPDATE) { - bgp_aggregate_increment(bgp, &bdi->dest->p, - bdi->path, bdi->afi, - bdi->safi); - bgp_process(bgp, bdi->dest, bdi->afi, - bdi->safi); - } - bgp_reuselist_del(list, bdi); - bgp_damp_info_free(bdi, 1); - } - } - - while ((bdi = SLIST_FIRST(&bdc->no_reuse_list)) != NULL) { - bgp_reuselist_del(&bdc->no_reuse_list, bdi); - bgp_damp_info_free(bdi, 1); - } - /* Free decay array */ XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array); bdc->decay_array_size = 0; @@ -526,78 +427,97 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc, XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index); bdc->reuse_index_size = 0; + /* Free reuse list array. */ XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list); bdc->reuse_list_size = 0; - - THREAD_OFF(bdc->t_reuse); } -/* Disable route flap dampening for a bgp instance. - * - * Please note that this function also gets used to free memory when deleting a - * bgp instance. - */ +/* Clean all the bgp_damp_info stored in reuse_list. */ +void bgp_damp_info_clean(afi_t afi, safi_t safi) +{ + unsigned int i; + struct bgp_damp_info *bdi, *next; + struct bgp_damp_config *bdc = &damp[afi][safi]; + + bdc->reuse_offset = 0; + + for (i = 0; i < bdc->reuse_list_size; i++) { + if (!bdc->reuse_list[i]) + continue; + + for (bdi = bdc->reuse_list[i]; bdi; bdi = next) { + next = bdi->next; + bgp_damp_info_free(bdi, 1, afi, safi); + } + bdc->reuse_list[i] = NULL; + } + + for (bdi = bdc->no_reuse_list; bdi; bdi = next) { + next = bdi->next; + bgp_damp_info_free(bdi, 1, afi, safi); + } + bdc->no_reuse_list = NULL; +} + int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi) { - struct bgp_damp_config *bdc; - - bdc = &bgp->damp[afi][safi]; - if (!bdc) - return 0; - + struct bgp_damp_config *bdc = &damp[afi][safi]; /* If it wasn't enabled, there's nothing to do. */ if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) return 0; /* Cancel reuse event. */ - thread_cancel(&bdc->t_reuse); + thread_cancel(&(bdc->t_reuse)); /* Clean BGP dampening information. */ - bgp_damp_info_clean(bgp, bdc, afi, safi); + bgp_damp_info_clean(afi, safi); + + /* Clear configuration */ + bgp_damp_config_clean(bdc); UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); - return 0; } -void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi) +void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi) { - struct bgp_damp_config *bdc; - - bdc = &bgp->damp[afi][safi]; - if (bdc->half_life == DEFAULT_HALF_LIFE * 60 - && bdc->reuse_limit == DEFAULT_REUSE - && bdc->suppress_value == DEFAULT_SUPPRESS - && bdc->max_suppress_time == bdc->half_life * 4) + if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60 + && damp[afi][safi].reuse_limit == DEFAULT_REUSE + && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS + && damp[afi][safi].max_suppress_time + == damp[afi][safi].half_life * 4) vty_out(vty, " bgp dampening\n"); - else if (bdc->half_life != DEFAULT_HALF_LIFE * 60 - && bdc->reuse_limit == DEFAULT_REUSE - && bdc->suppress_value == DEFAULT_SUPPRESS - && bdc->max_suppress_time == bdc->half_life * 4) - vty_out(vty, " bgp dampening %lld\n", bdc->half_life / 60LL); + else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60 + && damp[afi][safi].reuse_limit == DEFAULT_REUSE + && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS + && damp[afi][safi].max_suppress_time + == damp[afi][safi].half_life * 4) + vty_out(vty, " bgp dampening %lld\n", + damp[afi][safi].half_life / 60LL); else vty_out(vty, " bgp dampening %lld %d %d %lld\n", - bdc->half_life / 60LL, bdc->reuse_limit, - bdc->suppress_value, bdc->max_suppress_time / 60LL); + damp[afi][safi].half_life / 60LL, + damp[afi][safi].reuse_limit, + damp[afi][safi].suppress_value, + damp[afi][safi].max_suppress_time / 60LL); } -static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc, - unsigned int penalty, char *buf, - size_t len, bool use_json, - json_object *json) +static const char *bgp_get_reuse_time(unsigned int penalty, char *buf, + size_t len, afi_t afi, safi_t safi, + bool use_json, json_object *json) { time_t reuse_time = 0; struct tm tm; int time_store = 0; - if (penalty > bdc->reuse_limit) { + if (penalty > damp[afi][safi].reuse_limit) { reuse_time = (int)(DELTA_T - * ((log((double)bdc->reuse_limit / penalty)) - / (log(bdc->decay_array[1])))); + * ((log((double)damp[afi][safi].reuse_limit + / penalty)) + / (log(damp[afi][safi].decay_array[1])))); - if (reuse_time > bdc->max_suppress_time) - reuse_time = bdc->max_suppress_time; + if (reuse_time > damp[afi][safi].max_suppress_time) + reuse_time = damp[afi][safi].max_suppress_time; gmtime_r(&reuse_time, &tm); } else @@ -649,15 +569,14 @@ static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc, return buf; } -void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, - struct bgp_path_info *path, afi_t afi, safi_t safi, - json_object *json_path) +void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi, + safi_t safi, json_object *json_path) { struct bgp_damp_info *bdi; time_t t_now, t_diff; char timebuf[BGP_UPTIME_LEN]; int penalty; - struct bgp_damp_config *bdc = &bgp->damp[afi][safi]; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!path->extra) return; @@ -683,8 +602,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) - bgp_get_reuse_time(bdc, penalty, timebuf, - BGP_UPTIME_LEN, 1, json_path); + bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, + afi, safi, 1, json_path); } else { vty_out(vty, " Dampinfo: penalty %d, flapped %d times in %s", @@ -695,15 +614,14 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, ", reuse in %s", - bgp_get_reuse_time(bdc, penalty, timebuf, - BGP_UPTIME_LEN, 0, + bgp_get_reuse_time(penalty, timebuf, + BGP_UPTIME_LEN, afi, safi, 0, json_path)); vty_out(vty, "\n"); } } - const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, char *timebuf, size_t len, afi_t afi, safi_t safi, bool use_json, @@ -712,11 +630,7 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, struct bgp_damp_info *bdi; time_t t_now, t_diff; int penalty; - struct bgp_damp_config *bdc; - - bdc = get_active_bdc_from_pi(path, afi, safi); - if (!bdc) - return NULL; + struct bgp_damp_config *bdc = &damp[afi][safi]; if (!path->extra) return NULL; @@ -726,7 +640,7 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, /* If dampening is not enabled or there is no dampening information, return immediately. */ - if (!bdi) + if (!bdc || !bdi) return NULL; /* Calculate new penalty. */ @@ -734,23 +648,24 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, t_diff = t_now - bdi->t_updated; penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc); - return bgp_get_reuse_time(bdc, penalty, timebuf, len, use_json, json); + return bgp_get_reuse_time(penalty, timebuf, len, afi, safi, use_json, + json); } - static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty, afi_t afi, safi_t safi) { - struct bgp_damp_config *bdc; if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) { - bdc = &bgp->damp[afi][safi]; vty_out(vty, "Half-life time: %lld min\n", - (long long)bdc->half_life / 60); - vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit); - vty_out(vty, "Suppress penalty: %d\n", bdc->suppress_value); + (long long)damp[afi][safi].half_life / 60); + vty_out(vty, "Reuse penalty: %d\n", + damp[afi][safi].reuse_limit); + vty_out(vty, "Suppress penalty: %d\n", + damp[afi][safi].suppress_value); vty_out(vty, "Max suppress time: %lld min\n", - (long long)bdc->max_suppress_time / 60); - vty_out(vty, "Max suppress penalty: %u\n", bdc->ceiling); + (long long)damp[afi][safi].max_suppress_time / 60); + vty_out(vty, "Max suppress penalty: %u\n", + damp[afi][safi].ceiling); vty_out(vty, "\n"); } else vty_out(vty, "dampening not enabled for %s\n", @@ -763,8 +678,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi, uint16_t show_flags) { struct bgp *bgp; - bgp = bgp_get_default(); + if (bgp == NULL) { vty_out(vty, "No BGP process is configured\n"); return CMD_WARNING; @@ -803,132 +718,3 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi, } return CMD_SUCCESS; } - -void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi, - time_t half, unsigned int reuse, - unsigned int suppress, time_t max) -{ - struct bgp_damp_config *bdc; - - if (!peer) - return; - bdc = &peer->damp[afi][safi]; - if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) { - if (bdc->half_life == half && bdc->reuse_limit == reuse - && bdc->suppress_value == suppress - && bdc->max_suppress_time == max) - return; - bgp_peer_damp_disable(peer, afi, safi); - } - SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING); - bgp_damp_parameter_set(half, reuse, suppress, max, bdc); - bdc->afi = afi; - bdc->safi = safi; - thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE, - &bdc->t_reuse); -} - -/* Disable route flap dampening for a peer. - * - * Please note that this function also gets used to free memory when deleting a - * peer or peer group. - */ -void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi) -{ - struct bgp_damp_config *bdc; - - if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) - return; - bdc = &peer->damp[afi][safi]; - if (!bdc) - return; - bgp_damp_info_clean(peer->bgp, bdc, afi, safi); - UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING); -} - -void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer, afi_t afi, - safi_t safi) -{ - struct bgp_damp_config *bdc; - - bdc = &peer->damp[afi][safi]; - if (bdc->half_life == DEFAULT_HALF_LIFE * 60 - && bdc->reuse_limit == DEFAULT_REUSE - && bdc->suppress_value == DEFAULT_SUPPRESS - && bdc->max_suppress_time == bdc->half_life * 4) - vty_out(vty, " neighbor %s dampening\n", peer->host); - else if (bdc->half_life != DEFAULT_HALF_LIFE * 60 - && bdc->reuse_limit == DEFAULT_REUSE - && bdc->suppress_value == DEFAULT_SUPPRESS - && bdc->max_suppress_time == bdc->half_life * 4) - vty_out(vty, " neighbor %s dampening %lld\n", peer->host, - bdc->half_life / 60LL); - else - vty_out(vty, " neighbor %s dampening %lld %d %d %lld\n", - peer->host, bdc->half_life / 60LL, bdc->reuse_limit, - bdc->suppress_value, bdc->max_suppress_time / 60LL); -} - -static void bgp_print_peer_dampening_parameters(struct vty *vty, - struct peer *peer, afi_t afi, - safi_t safi, bool use_json, - json_object *json) -{ - struct bgp_damp_config *bdc; - - if (!peer) - return; - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING)) { - bdc = &peer->damp[afi][safi]; - if (!bdc) - return; - if (use_json) { - json_object_int_add(json, "halfLifeSecs", - bdc->half_life); - json_object_int_add(json, "reusePenalty", - bdc->reuse_limit); - json_object_int_add(json, "suppressPenalty", - bdc->suppress_value); - json_object_int_add(json, "maxSuppressTimeSecs", - bdc->max_suppress_time); - json_object_int_add(json, "maxSuppressPenalty", - bdc->ceiling); - } else { - vty_out(vty, "Half-life time: %lld min\n", - (long long)bdc->half_life / 60); - vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit); - vty_out(vty, "Suppress penalty: %d\n", - bdc->suppress_value); - vty_out(vty, "Max suppress time: %lld min\n", - (long long)bdc->max_suppress_time / 60); - vty_out(vty, "Max suppress penalty: %u\n", - bdc->ceiling); - vty_out(vty, "\n"); - } - } else if (!use_json) - vty_out(vty, "neighbor dampening not enabled for %s\n", - get_afi_safi_str(afi, safi, false)); -} - -void bgp_show_peer_dampening_parameters(struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi, bool use_json) -{ - json_object *json; - - if (use_json) { - json = json_object_new_object(); - json_object_string_add(json, "addressFamily", - get_afi_safi_str(afi, safi, false)); - bgp_print_peer_dampening_parameters(vty, peer, afi, safi, true, - json); - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - vty_out(vty, "\nFor address family: %s\n", - get_afi_safi_str(afi, safi, false)); - bgp_print_peer_dampening_parameters(vty, peer, afi, safi, false, - NULL); - } -} diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index fc03b97c13..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; @@ -61,12 +61,8 @@ struct bgp_damp_info { afi_t afi; safi_t safi; - - SLIST_ENTRY(bgp_damp_info) entry; }; -SLIST_HEAD(reuselist, bgp_damp_info); - /* Specified parameter set configuration. */ struct bgp_damp_config { /* Value over which routes suppressed. */ @@ -104,11 +100,11 @@ struct bgp_damp_config { int *reuse_index; /* Reuse list array per-set based. */ - struct reuselist *reuse_list; - unsigned int reuse_offset; + struct bgp_damp_info **reuse_list; + int reuse_offset; /* All dampening information which is not on reuse list. */ - struct reuselist no_reuse_list; + struct bgp_damp_info *no_reuse_list; /* Reuse timer thread per-set base. */ struct thread *t_reuse; @@ -136,8 +132,6 @@ struct bgp_damp_config { #define REUSE_LIST_SIZE 256 #define REUSE_ARRAY_SIZE 1024 -extern struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi, - afi_t afi, safi_t safi); extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int, unsigned int, time_t); extern int bgp_damp_disable(struct bgp *, afi_t, safi_t); @@ -145,16 +139,13 @@ extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest, afi_t afi, safi_t safi, int attr_change); extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest, afi_t afi, safi_t saff); -extern void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw); -extern void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc, - afi_t afi, safi_t safi); -extern void bgp_damp_config_clean(struct bgp_damp_config *bdc); +extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw, + afi_t afi, safi_t safi); +extern void bgp_damp_info_clean(afi_t afi, safi_t safi); extern int bgp_damp_decay(time_t, int, struct bgp_damp_config *damp); -extern void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi); -extern void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp, - struct bgp_path_info *path, afi_t afi, - safi_t safi, json_object *json_path); +extern void bgp_config_write_damp(struct vty *, afi_t afi, safi_t safi); +extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, + afi_t afi, safi_t safi, json_object *json_path); extern const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, char *timebuf, size_t len, afi_t afi, @@ -162,14 +153,5 @@ extern const char *bgp_damp_reuse_time_vty(struct vty *vty, json_object *json); extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t, uint16_t); -extern void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi, - time_t half, unsigned int reuse, - unsigned int suppress, time_t max); -extern void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi); -extern void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi); -extern void bgp_show_peer_dampening_parameters(struct vty *vty, - struct peer *peer, afi_t afi, - safi_t safi, bool use_json); #endif /* _QUAGGA_BGP_DAMP_H */ 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 fb6781687b..716ba26305 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -218,11 +218,11 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) return; e = *extra; - if (e->damp_info) - bgp_damp_info_free(e->damp_info, 0); - e->damp_info = NULL; + bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi, + e->damp_info->safi); + e->damp_info = NULL; if (e->parent) { struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent; @@ -3391,16 +3391,14 @@ static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi, /* apply dampening, if result is suppressed, we'll be retaining * the bgp_path_info in the RIB for historical reference. */ - if (peer->sort == BGP_PEER_EBGP) { - if (get_active_bdc_from_pi(pi, afi, safi)) { - if (bgp_damp_withdraw(pi, dest, afi, safi, 0) - == BGP_DAMP_SUPPRESSED) { - bgp_aggregate_decrement(peer->bgp, p, pi, afi, - safi); - return; - } + if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP) + if ((bgp_damp_withdraw(pi, dest, afi, safi, 0)) + == BGP_DAMP_SUPPRESSED) { + bgp_aggregate_decrement(peer->bgp, p, pi, afi, + safi); + return; } - } #ifdef ENABLE_BGP_VNC if (safi == SAFI_MPLS_VPN) { @@ -3849,7 +3847,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, || memcmp(&(bgp_path_info_extra_get(pi))->label, label, num_labels * sizeof(mpls_label_t)) == 0)) { - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { if (bgp_debug_update(peer, p, NULL, 1)) { @@ -3951,11 +3950,11 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_aggregate_decrement(bgp, p, pi, afi, safi); /* Update bgp route dampening information. */ - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) { /* This is implicit withdraw so we should update - * dampening information. - */ + dampening + information. */ if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) bgp_damp_withdraw(pi, dest, afi, safi, 1); } @@ -4078,7 +4077,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, #endif /* Update bgp route dampening information. */ - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) { /* Now we do normal update dampening. */ ret = bgp_damp_update(pi, dest, afi, safi); @@ -10439,7 +10438,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } if (path->extra && path->extra->damp_info) - bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path); + bgp_damp_info_vty(vty, path, afi, safi, json_path); /* Remote Label */ if (path->extra && bgp_is_valid_label(&path->extra->label[0]) @@ -14647,7 +14646,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, pi_temp = pi->next; bgp_damp_info_free( pi->extra->damp_info, - 1); + 1, afi, safi); pi = pi_temp; } else pi = pi->next; @@ -14667,24 +14666,9 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, while (pi) { if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; - struct bgp_damp_info *bdi = - pi->extra->damp_info; - if (bdi->lastrecord - == BGP_RECORD_UPDATE) { - bgp_aggregate_increment( - bgp, - &bdi->dest->p, - bdi->path, - bdi->afi, - bdi->safi); - bgp_process(bgp, - bdi->dest, - bdi->afi, - bdi->safi); - } bgp_damp_info_free( pi->extra->damp_info, - 1); + 1, afi, safi); pi = pi_temp; } else pi = pi->next; @@ -14706,9 +14690,7 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP, - SAFI_UNICAST); + bgp_damp_info_clean(AFI_IP, SAFI_UNICAST); return CMD_SUCCESS; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 06facdd389..63b2fbd4e6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8046,93 +8046,6 @@ DEFPY( return CMD_SUCCESS; } -DEFPY(neighbor_damp, - neighbor_damp_cmd, - "neighbor $neighbor dampening [(1-45)$half [(1-20000)$reuse (1-20000)$suppress (1-255)$max]]", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable neighbor route-flap dampening\n" - "Half-life time for the penalty\n" - "Value to start reusing a route\n" - "Value to start suppressing a route\n" - "Maximum duration to suppress a stable route\n") -{ - struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); - - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - if (!half) - half = DEFAULT_HALF_LIFE; - if (!reuse) { - reuse = DEFAULT_REUSE; - suppress = DEFAULT_SUPPRESS; - max = half * 4; - } - if (suppress < reuse) { - vty_out(vty, - "Suppress value cannot be less than reuse value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - bgp_peer_damp_enable(peer, bgp_node_afi(vty), bgp_node_safi(vty), - half * 60, reuse, suppress, max * 60); - return CMD_SUCCESS; -} - -DEFPY(no_neighbor_damp, - no_neighbor_damp_cmd, - "no neighbor $neighbor dampening [HALF [REUSE SUPPRESS MAX]]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable neighbor route-flap dampening\n" - "Half-life time for the penalty\n" - "Value to start reusing a route\n" - "Value to start suppressing a route\n" - "Maximum duration to suppress a stable route\n") -{ - struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); - - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - bgp_peer_damp_disable(peer, bgp_node_afi(vty), bgp_node_safi(vty)); - return CMD_SUCCESS; -} - -DEFPY (show_ip_bgp_neighbor_damp_param, - show_ip_bgp_neighbor_damp_param_cmd, - "show [ip] bgp [ [unicast]] neighbors $neighbor dampening parameters [json]$json", - SHOW_STR - IP_STR - BGP_STR - BGP_AFI_HELP_STR - "Address Family modifier\n" - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Neighbor route-flap dampening information\n" - "Display detail of configured dampening parameters\n" - JSON_STR) -{ - bool use_json = false; - int idx = 0; - afi_t afi = AFI_IP; - safi_t safi = SAFI_UNICAST; - struct peer *peer; - - if (argv_find(argv, argc, "ip", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv4", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv6", &idx)) - afi = AFI_IP6; - peer = peer_and_group_lookup_vty(vty, neighbor); - if (!peer) - return CMD_WARNING; - if (json) - use_json = true; - bgp_show_peer_dampening_parameters(vty, peer, afi, safi, use_json); - return CMD_SUCCESS; -} - static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, struct ecommunity **list, bool is_rt6) { @@ -16794,9 +16707,6 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, : ""); } } - - if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) - bgp_config_write_peer_damp(vty, peer, afi, safi); } /* Address family based peer configuration display. */ @@ -16849,7 +16759,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, /* BGP flag dampening. */ if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - bgp_config_write_damp(vty, bgp, afi, safi); + bgp_config_write_damp(vty, afi, safi); for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi); @@ -18658,23 +18568,6 @@ void bgp_vty_init(void) install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd); install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd); - /* "neighbor dampening" commands. */ - install_element(BGP_NODE, &neighbor_damp_cmd); - install_element(BGP_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV4_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV4_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV4M_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV4M_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV4L_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV4L_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV6_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV6_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV6M_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV6M_NODE, &no_neighbor_damp_cmd); - install_element(BGP_IPV6L_NODE, &neighbor_damp_cmd); - install_element(BGP_IPV6L_NODE, &no_neighbor_damp_cmd); - install_element(VIEW_NODE, &show_ip_bgp_neighbor_damp_param_cmd); - /* address-family commands. */ install_element(BGP_NODE, &address_family_ipv4_safi_cmd); install_element(BGP_NODE, &address_family_ipv6_safi_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2d84acb7bd..591fc1214c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2412,14 +2412,6 @@ int peer_delete(struct peer *peer) if (peer->bfd_config) bgp_peer_remove_bfd_config(peer); - /* Delete peer route flap dampening configuration. This needs to happen - * before removing the peer from peer groups. - */ - FOREACH_AFI_SAFI (afi, safi) - if (peer_af_flag_check(peer, afi, safi, - PEER_FLAG_CONFIG_DAMPENING)) - bgp_peer_damp_disable(peer, afi, safi); - /* If this peer belongs to peer group, clear up the relationship. */ if (peer->group) { @@ -3603,11 +3595,6 @@ int bgp_delete(struct bgp *bgp) BGP_TIMER_OFF(gr_info->t_route_select); } - /* Delete route flap dampening configuration */ - FOREACH_AFI_SAFI (afi, safi) { - bgp_damp_disable(bgp, afi, safi); - } - if (BGP_DEBUG(zebra, ZEBRA)) { if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) zlog_debug("Deleting Default VRF"); 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]; diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index ef72c5030a..5df149a174 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -515,54 +515,28 @@ Disable checking if nexthop is connected on EBGP sessions Route Flap Dampening -------------------- -.. clicmd:: bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]] +.. clicmd:: bgp dampening (1-45) (1-20000) (1-20000) (1-255) - This command enables (with optionally specified dampening parameters) or - disables route-flap dampening for all routes of a BGP instance. - -.. clicmd:: neighbor PEER dampening [(1-45) [(1-20000) (1-20000) (1-255)]] - - This command enables (with optionally specified dampening parameters) or - disables route-flap dampening for all routes learned from a BGP peer. - -.. clicmd:: neighbor GROUP dampening [(1-45) [(1-20000) (1-20000) (1-255)]] - - This command enables (with optionally specified dampening parameters) or - disables route-flap dampening for all routes learned from peers of a peer - group. + This command enables BGP route-flap dampening and specifies dampening parameters. half-life - Half-life time for the penalty in minutes (default value: 15). + Half-life time for the penalty reuse-threshold - Value to start reusing a route (default value: 750). + Value to start reusing a route suppress-threshold - Value to start suppressing a route (default value: 2000). + Value to start suppressing a route max-suppress - Maximum duration to suppress a stable route in minutes (default value: - 60). + Maximum duration to suppress a stable route The route-flap damping algorithm is compatible with :rfc:`2439`. The use of - these commands is not recommended nowadays. + this command is not recommended nowadays. At the moment, route-flap dampening is not working per VRF and is working only for IPv4 unicast and multicast. - With different parameter sets configurable for BGP instances, peer groups and - peers, the active dampening profile for a route is chosen on the fly, - allowing for various changes in configuration (i.e. peer group memberships) - during runtime. The parameter sets are taking precedence in the following - order: - - 1. Peer - 2. Peer group - 3. BGP instance - - The negating commands do not allow to exclude a peer/peer group from a peer - group/BGP instances configuration. - .. seealso:: https://www.ripe.net/publications/docs/ripe-378 diff --git a/tests/topotests/bgp_features/exabgp.env b/tests/topotests/bgp_features/exabgp.env deleted file mode 100644 index 6c554f5fa8..0000000000 --- a/tests/topotests/bgp_features/exabgp.env +++ /dev/null @@ -1,53 +0,0 @@ - -[exabgp.api] -encoder = text -highres = false -respawn = false -socket = '' - -[exabgp.bgp] -openwait = 60 - -[exabgp.cache] -attributes = true -nexthops = true - -[exabgp.daemon] -daemonize = true -pid = '/var/run/exabgp/exabgp.pid' -user = 'exabgp' - -[exabgp.log] -all = false -configuration = true -daemon = true -destination = '/var/log/exabgp.log' -enable = true -level = INFO -message = false -network = true -packets = false -parser = false -processes = true -reactor = true -rib = false -routes = false -short = false -timers = false - -[exabgp.pdb] -enable = false - -[exabgp.profile] -enable = false -file = '' - -[exabgp.reactor] -speed = 1.0 - -[exabgp.tcp] -acl = false -bind = '' -delay = 0 -once = false -port = 179 diff --git a/tests/topotests/bgp_features/peer1/exa_readpipe.py b/tests/topotests/bgp_features/peer1/exa_readpipe.py deleted file mode 100644 index 9e689a27e3..0000000000 --- a/tests/topotests/bgp_features/peer1/exa_readpipe.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -"Helper script to read api commands from a pipe and feed them to ExaBGP" - -import sys - -if len(sys.argv) != 2: - sys.exit(1) -fifo = sys.argv[1] - -while True: - pipe = open(fifo, "r") - with pipe: - line = pipe.readline().strip() - if line != "": - sys.stdout.write("{}\n".format(line)) - sys.stdout.flush() - pipe.close() - -sys.exit(0) diff --git a/tests/topotests/bgp_features/peer1/exabgp.cfg b/tests/topotests/bgp_features/peer1/exabgp.cfg deleted file mode 100644 index 2e95252cf6..0000000000 --- a/tests/topotests/bgp_features/peer1/exabgp.cfg +++ /dev/null @@ -1,12 +0,0 @@ -group exabgp { - process announce-routes { - run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer1.in"; - encoder text; - } - neighbor 192.168.101.1 { - router-id 192.168.101.3; - local-address 192.168.101.3; - local-as 65403; - peer-as 65000; - } -} diff --git a/tests/topotests/bgp_features/peer2/exa_readpipe.py b/tests/topotests/bgp_features/peer2/exa_readpipe.py deleted file mode 100644 index 9e689a27e3..0000000000 --- a/tests/topotests/bgp_features/peer2/exa_readpipe.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -"Helper script to read api commands from a pipe and feed them to ExaBGP" - -import sys - -if len(sys.argv) != 2: - sys.exit(1) -fifo = sys.argv[1] - -while True: - pipe = open(fifo, "r") - with pipe: - line = pipe.readline().strip() - if line != "": - sys.stdout.write("{}\n".format(line)) - sys.stdout.flush() - pipe.close() - -sys.exit(0) diff --git a/tests/topotests/bgp_features/peer2/exabgp.cfg b/tests/topotests/bgp_features/peer2/exabgp.cfg deleted file mode 100644 index 1f65547bc5..0000000000 --- a/tests/topotests/bgp_features/peer2/exabgp.cfg +++ /dev/null @@ -1,12 +0,0 @@ -group exabgp { - process announce-routes { - run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer2.in"; - encoder text; - } - neighbor 192.168.101.1 { - router-id 192.168.101.4; - local-address 192.168.101.4; - local-as 65404; - peer-as 65000; - } -} diff --git a/tests/topotests/bgp_features/peer3/exa_readpipe.py b/tests/topotests/bgp_features/peer3/exa_readpipe.py deleted file mode 100644 index 9e689a27e3..0000000000 --- a/tests/topotests/bgp_features/peer3/exa_readpipe.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -"Helper script to read api commands from a pipe and feed them to ExaBGP" - -import sys - -if len(sys.argv) != 2: - sys.exit(1) -fifo = sys.argv[1] - -while True: - pipe = open(fifo, "r") - with pipe: - line = pipe.readline().strip() - if line != "": - sys.stdout.write("{}\n".format(line)) - sys.stdout.flush() - pipe.close() - -sys.exit(0) diff --git a/tests/topotests/bgp_features/peer3/exabgp.cfg b/tests/topotests/bgp_features/peer3/exabgp.cfg deleted file mode 100644 index 8632cc86c5..0000000000 --- a/tests/topotests/bgp_features/peer3/exabgp.cfg +++ /dev/null @@ -1,12 +0,0 @@ -group exabgp { - process announce-routes { - run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer3.in"; - encoder text; - } - neighbor 192.168.101.1 { - router-id 192.168.101.5; - local-address 192.168.101.5; - local-as 65405; - peer-as 65000; - } -} diff --git a/tests/topotests/bgp_features/peer4/exa_readpipe.py b/tests/topotests/bgp_features/peer4/exa_readpipe.py deleted file mode 100644 index 9e689a27e3..0000000000 --- a/tests/topotests/bgp_features/peer4/exa_readpipe.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -"Helper script to read api commands from a pipe and feed them to ExaBGP" - -import sys - -if len(sys.argv) != 2: - sys.exit(1) -fifo = sys.argv[1] - -while True: - pipe = open(fifo, "r") - with pipe: - line = pipe.readline().strip() - if line != "": - sys.stdout.write("{}\n".format(line)) - sys.stdout.flush() - pipe.close() - -sys.exit(0) diff --git a/tests/topotests/bgp_features/peer4/exabgp.cfg b/tests/topotests/bgp_features/peer4/exabgp.cfg deleted file mode 100644 index 06bc0d6e64..0000000000 --- a/tests/topotests/bgp_features/peer4/exabgp.cfg +++ /dev/null @@ -1,12 +0,0 @@ -group exabgp { - process announce-routes { - run "/etc/exabgp/exa_readpipe.py /var/run/exabgp_peer4.in"; - encoder text; - } - neighbor 192.168.101.1 { - router-id 192.168.101.6; - local-address 192.168.101.6; - local-as 65406; - peer-as 65000; - } -} diff --git a/tests/topotests/bgp_features/r1/bgp_damp_announced.json b/tests/topotests/bgp_features/r1/bgp_damp_announced.json deleted file mode 100644 index cb4a2c9b2f..0000000000 --- a/tests/topotests/bgp_features/r1/bgp_damp_announced.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "localAS":65000, - "routes":{ - "192.168.31.0/24": [ { "valid":true, "network":"192.168.31.0\/24", "peerId":"192.168.101.3" } ], - "192.168.32.0/24": [ { "valid":true, "network":"192.168.32.0\/24", "peerId":"192.168.101.3" } ], - "192.168.33.0/24": [ { "valid":true, "network":"192.168.33.0\/24", "peerId":"192.168.101.3" } ], - "192.168.34.0/24": [ { "valid":true, "network":"192.168.34.0\/24", "peerId":"192.168.101.3" } ], - "192.168.41.0/24": [ { "valid":true, "network":"192.168.41.0\/24", "peerId":"192.168.101.4" } ], - "192.168.42.0/24": [ { "valid":true, "network":"192.168.42.0\/24", "peerId":"192.168.101.4" } ], - "192.168.43.0/24": [ { "valid":true, "network":"192.168.43.0\/24", "peerId":"192.168.101.4" } ], - "192.168.44.0/24": [ { "valid":true, "network":"192.168.44.0\/24", "peerId":"192.168.101.4" } ], - "192.168.51.0/24": [ { "valid":true, "network":"192.168.51.0\/24", "peerId":"192.168.101.5" } ], - "192.168.52.0/24": [ { "valid":true, "network":"192.168.52.0\/24", "peerId":"192.168.101.5" } ], - "192.168.53.0/24": [ { "valid":true, "network":"192.168.53.0\/24", "peerId":"192.168.101.5" } ], - "192.168.54.0/24": [ { "valid":true, "network":"192.168.54.0\/24", "peerId":"192.168.101.5" } ], - "192.168.61.0/24": [ { "valid":true, "network":"192.168.61.0\/24", "peerId":"192.168.101.6" } ], - "192.168.62.0/24": [ { "valid":true, "network":"192.168.62.0\/24", "peerId":"192.168.101.6" } ], - "192.168.63.0/24": [ { "valid":true, "network":"192.168.63.0\/24", "peerId":"192.168.101.6" } ], - "192.168.64.0/24": [ { "valid":true, "network":"192.168.64.0\/24", "peerId":"192.168.101.6" } ] - } -} diff --git a/tests/topotests/bgp_features/r1/bgp_damp_setup.json b/tests/topotests/bgp_features/r1/bgp_damp_setup.json deleted file mode 100644 index f9f89db894..0000000000 --- a/tests/topotests/bgp_features/r1/bgp_damp_setup.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ipv4Unicast":{ - "peers":{ - "192.168.101.3":{"remoteAs":65403, "state":"Established"}, - "192.168.101.4":{"remoteAs":65404, "state":"Established"}, - "192.168.101.5":{"remoteAs":65405, "state":"Established"}, - "192.168.101.6":{"remoteAs":65406, "state":"Established"} - } - } -} diff --git a/tests/topotests/bgp_features/r2/bgp_damp_announced.json b/tests/topotests/bgp_features/r2/bgp_damp_announced.json deleted file mode 100644 index 9394358f82..0000000000 --- a/tests/topotests/bgp_features/r2/bgp_damp_announced.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "localAS":65000, - "routes":{ - "192.168.31.0/24": [ { "network":"192.168.31.0\/24", "peerId":"192.168.0.1" } ], - "192.168.32.0/24": [ { "network":"192.168.32.0\/24", "peerId":"192.168.0.1" } ], - "192.168.33.0/24": [ { "network":"192.168.33.0\/24", "peerId":"192.168.0.1" } ], - "192.168.34.0/24": [ { "network":"192.168.34.0\/24", "peerId":"192.168.0.1" } ], - "192.168.41.0/24": [ { "network":"192.168.41.0\/24", "peerId":"192.168.0.1" } ], - "192.168.42.0/24": [ { "network":"192.168.42.0\/24", "peerId":"192.168.0.1" } ], - "192.168.43.0/24": [ { "network":"192.168.43.0\/24", "peerId":"192.168.0.1" } ], - "192.168.44.0/24": [ { "network":"192.168.44.0\/24", "peerId":"192.168.0.1" } ], - "192.168.51.0/24": [ { "network":"192.168.51.0\/24", "peerId":"192.168.0.1" } ], - "192.168.52.0/24": [ { "network":"192.168.52.0\/24", "peerId":"192.168.0.1" } ], - "192.168.53.0/24": [ { "network":"192.168.53.0\/24", "peerId":"192.168.0.1" } ], - "192.168.54.0/24": [ { "network":"192.168.54.0\/24", "peerId":"192.168.0.1" } ], - "192.168.61.0/24": [ { "network":"192.168.61.0\/24", "peerId":"192.168.0.1" } ], - "192.168.62.0/24": [ { "network":"192.168.62.0\/24", "peerId":"192.168.0.1" } ], - "192.168.63.0/24": [ { "network":"192.168.63.0\/24", "peerId":"192.168.0.1" } ], - "192.168.64.0/24": [ { "network":"192.168.64.0\/24", "peerId":"192.168.0.1" } ] - } -} diff --git a/tests/topotests/bgp_features/r2/bgp_damp_withdrawn.json b/tests/topotests/bgp_features/r2/bgp_damp_withdrawn.json deleted file mode 100644 index f3c54a70a1..0000000000 --- a/tests/topotests/bgp_features/r2/bgp_damp_withdrawn.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "192.168.31.0/24": null, - "192.168.32.0/24": null, - "192.168.33.0/24": null, - "192.168.34.0/24": null, - "192.168.41.0/24": null, - "192.168.42.0/24": null, - "192.168.43.0/24": null, - "192.168.44.0/24": null, - "192.168.51.0/24": null, - "192.168.52.0/24": null, - "192.168.53.0/24": null, - "192.168.54.0/24": null, - "192.168.61.0/24": null, - "192.168.62.0/24": null, - "192.168.63.0/24": null, - "192.168.64.0/24": null -} diff --git a/tests/topotests/bgp_features/test_bgp_features.py b/tests/topotests/bgp_features/test_bgp_features.py index a68508c4ae..d19b7722d0 100644 --- a/tests/topotests/bgp_features/test_bgp_features.py +++ b/tests/topotests/bgp_features/test_bgp_features.py @@ -33,7 +33,6 @@ import sys import pytest import re import time -from time import sleep # Save the Current Working Directory to find configuration files. CWD = os.path.dirname(os.path.realpath(__file__)) @@ -67,14 +66,6 @@ class BGPFeaturesTopo1(Topo): for rtrNum in range(1, 6): tgen.add_router("r{}".format(rtrNum)) - # create ExaBGP peers - for peer_num in range(1, 5): - tgen.add_exabgp_peer( - "peer{}".format(peer_num), - ip="192.168.101.{}".format(peer_num + 2), - defaultRoute="via 192.168.101.1", - ) - # Setup Switches and connections for swNum in range(1, 11): tgen.add_switch("sw{}".format(swNum)) @@ -100,12 +91,6 @@ class BGPFeaturesTopo1(Topo): tgen.gears["r2"].add_link(tgen.gears["sw5"]) tgen.gears["r5"].add_link(tgen.gears["sw5"]) - # Add ExaBGP peers to sw4 - tgen.gears["peer1"].add_link(tgen.gears["sw4"]) - tgen.gears["peer2"].add_link(tgen.gears["sw4"]) - tgen.gears["peer3"].add_link(tgen.gears["sw4"]) - tgen.gears["peer4"].add_link(tgen.gears["sw4"]) - ##################################################### # @@ -1110,662 +1095,6 @@ def test_bgp_delayopen_dual(): # end test_bgp_delayopen_dual -def test_bgp_dampening_setup(): - "BGP route-flap dampening test setup" - - # This test starts four ExaBGP peers, adds them as neighbors to the - # configuration of router r1 and checks if connections get established. - - tgen = get_topogen() - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting BGP route-flap dampening test setup") - - # Start ExaBGP peers connected to r1 via switch 4 - logger.info("Starting ExaBGP peers") - for peer_num in range(1, 5): - logger.info("Creating named pipe for ExaBGP peer peer{}".format(peer_num)) - fifo_in = "/var/run/exabgp_peer{}.in".format(peer_num) - if os.path.exists(fifo_in): - os.remove(fifo_in) - os.mkfifo(fifo_in, 0o777) - logger.info("Starting ExaBGP on peer peer{}".format(peer_num)) - peer = tgen.gears["peer{}".format(peer_num)] - peer_dir = os.path.join(CWD, "peer{}".format(peer_num)) - env_file = os.path.join(CWD, "exabgp.env") - peer.start(peer_dir, env_file) - - # Add ExaBGP peers to configuration of router r2 - logger.info("Adding ExaBGP peers as neighbors to configuration of router r2") - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.3 remote-as 65403"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 route-map testmap-in"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 route-map testmap-out"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.4 remote-as 65404"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.4 route-map testmap-in"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.4 route-map testmap-out"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.5 remote-as 65405"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 route-map testmap-in"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 route-map testmap-out"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.6 remote-as 65406"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.6 route-map testmap-in"' - ) - tgen.net["r1"].cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.6 route-map testmap-out"' - ) - - # Check if exabgp peers are up and running - logger.info("Checking for established connections to ExaBGP peers on router r1") - router = tgen.gears["r1"] - reffile = os.path.join(CWD, "r1/bgp_damp_setup.json") - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, router, "show ip bgp summary json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=10, wait=1) - assertmsg = ( - "BGP session on r1 did not establish connections with one ore more ExaBGP peers" - ) - assert res is None, assertmsg - - # end test_bgp_dampening_setup - - -def test_bgp_dampening_route_announce(): - "Test of BGP route-flap dampening route announcement" - - # This test checks if the four ExaBGP peers can announce routes to router - # r1 and if these routes get forwarded to router r2. - - tgen = get_topogen() - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting test of BGP route-flap dampening route announcement") - - # Announce routes on exabgp peers to r2 - logger.info("Announcing routes on ExaBGP peers to r1") - for prefix_iter in range(1, 5): - for peer_num in range(1, 5): - pipe = open("/run/exabgp_peer{}.in".format(peer_num), "w") - with pipe: - pipe.write( - "announce route 192.168.{}{}.0/24 next-hop 192.168.101.{}\n".format( - (peer_num + 2), prefix_iter, (peer_num + 2) - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Check if routes announced by ExaBGP peers are present in RIB of router r1 - logger.info( - "Checking if routes announced by ExaBGP peers are present in RIB of router r1" - ) - router = tgen.gears["r1"] - reffile = os.path.join(CWD, "r1/bgp_damp_announced.json") - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, router, "show ip bgp json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=10, wait=1) - assertmsg = ( - "BGP session on router r1 did not receive routes announced by ExaBGP peers" - ) - assert res is None, assertmsg - - # Check if routes announced by ExaBGP peers to router r1 have been forwarded - # and are now present in RIB of router r2 - logger.info( - "Checking if forwarded routes announced by ExaBGP peers are present in RIB of router r2" - ) - router = tgen.gears["r2"] - reffile = os.path.join(CWD, "r2/bgp_damp_announced.json") - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, router, "show ip bgp json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=10, wait=1) - assertmsg = "BGP session on router r2 did not receive routes announced by ExaBGP peers forwarded by router r1" - assert res is None, assertmsg - - # end test_bgp_dampening_route_announce - - -def test_bgp_dampening_disabled(): - "Test of BGP route-flapping with dampening disabled" - - # This test verifies that flapped routes do not get withdrawn from the RIB - # of router r1 if dampening is disabled. - - tgen = get_topogen() - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting test of BGP route-flapping with dampening disabled") - - # Flapping routes on ExaBGP peer peer1 - logger.info( - "Flapping routes on ExaBGP peer peer1 with route-flap dampening disabled" - ) - for _ in range(1, 5): - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer1.in", "w") - with pipe: - pipe.write( - "withdraw route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - sleep(1) # Give the BGP session on router r1 time to process routes - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer1.in", "w") - with pipe: - pipe.write( - "announce route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Verify flapped routes are still present in RIB of router r1 - logger.info( - "Verifying that the flapped routes are still present in RIB of router r1" - ) - router = tgen.gears["r1"] - reffile = os.path.join(CWD, "r1/bgp_damp_announced.json") - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, router, "show ip bgp json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=10, wait=1) - assertmsg = "BGP session on router r1 removed flapped routes despite route-flap dampening being disabled" - assert res is None, assertmsg - - # end test_bgp_dampening_disabled - - -def test_bgp_dampening_config(): - "Test of BGP route-flap dampening configuration" - - # This test adds peer-group group1 with peers peer1 and peer2 to the - # configuration of router r1, sets up dampening configurations with - # different profiles and verifies the configured dampening parameters. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting test of BGP route-flap dampening configuration") - - # Add peer-group group1 with peers peer1 and peer2 - logger.info( - "Creating peer-group group1 and adding ExaBGP peers peer1 and peer2 to it" - ) - r_1.cmd('vtysh -c "conf t" -c "router bgp 65000" -c "neighbor group1 peer-group"') - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.3 peer-group group1"' - ) # peer1 - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "neighbor 192.168.101.4 peer-group group1"' - ) # peer2 - - # Enable different dampening profiles for peer1, peer3, group1 and global - # configuration - logger.info( - "Enabling different dampening profiles for peer1, peer3, group1 and global configuration" - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "bgp dampening 30 300 900 90"' - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor group1 dampening 20 200 600 60"' - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.3 dampening 10 100 300 30"' - ) # peer1 - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "neighbor 192.168.101.5 dampening 10 100 300 30"' - ) # peer3 - - # Verify route-flap dampening configuration - logger.info("Verifying route-flap dampening configuration on router r1") - vtyout = r_1.cmd('vtysh -c "show running-config"') - assertmsg = "BGP Session on r1 does not show enabled global route-flap dampening in running configuration" - assert re.search("bgp dampening 30 300 900 90", vtyout), assertmsg - assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer-group group1 in running configuration" - assert re.search("neighbor group1 dampening 20 200 600 60", vtyout), assertmsg - assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer peer1 in running configuration" - assert re.search( - "neighbor 192.168.101.3 dampening 10 100 300 30", vtyout - ), assertmsg - assertmsg = "BGP Session on r1 does not show route-flap dampening enabled for peer peer3 in running configuration" - assert re.search( - "neighbor 192.168.101.5 dampening 10 100 300 30", vtyout - ), assertmsg - - # end test_bgp_dampening_config - - -def test_bgp_dampening_profile_peer_over_group(): - "Test of BGP route-flap dampening profile preferences: peer over group" - - # This test verifies that the dampening profile of a peer takes precedence - # over the dampening profile of its peer-group by flapping the peers routes - # until dampened and comparing the reuse times to the one specified in the - # dampening configuration. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info( - "Starting test of BGP route-flap dampening profile preferences: peer over group" - ) - - # Flapping routes on ExaBGP peer peer1 - logger.info( - "Flapping routes on ExaBGP peer peer1 with route-flap dampening enabled" - ) - for _ in range(1, 5): - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer1.in", "w") - with pipe: - pipe.write( - "withdraw route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - sleep(1) # Give the BGP session on router r1 time to process routes - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer1.in", "w") - with pipe: - pipe.write( - "announce route 192.168.3{}.0/24 next-hop 192.168.101.3\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Check damped paths on r1 for routes of peer1 witn peer profile - logger.info( - "Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer1" - ) - sleep(5) # Wait 5 seconds for paths to show up in dampened-paths list - vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"') - routes = re.findall(r"\*d 192\.168\.3\d\.0\/24.*", vtyout) - assertmsg = ( - "BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer1" - ) - assert len(routes) == 4, assertmsg - assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer1" - for route in routes: - assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time - 35 > int(route.split()[3].split(":")[1]) > 25 - ), assertmsg # minutes of reuse time - - # end test_bgp_dampening_profile_peer_over_group - - -def test_bgp_dampening_profile_group_over_global(): - "Test of BGP route-flap dampening profile preferences: group over global" - - # This test verifies that the dampening profile of a peer-group takes - # precedence over the global dampening profile by flapping the routes of a - # peer-group member until dampened and comparing the reuse times to the one - # specified in the dampening configuration. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info( - "Starting test of BGP route-flap dampening profile preferences: group over global" - ) - - # Flapping routes on ExaBGP peer peer2 - logger.info( - "Flapping routes on ExaBGP peer peer2 with route-flap dampening enabled" - ) - for _ in range(1, 5): - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer2.in", "w") - with pipe: - pipe.write( - "withdraw route 192.168.4{}.0/24 next-hop 192.168.101.4\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - sleep(1) # Give the BGP session on router r1 time to process routes - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer2.in", "w") - with pipe: - pipe.write( - "announce route 192.168.4{}.0/24 next-hop 192.168.101.4\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Check damped paths on r1 for routes of peer2 witn group profile - logger.info( - "Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer2" - ) - sleep(5) # wait 5 seconds for paths to shop up in damp list - vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"') - routes = re.findall(r"\*d 192\.168\.4\d\.0\/24.*", vtyout) - assertmsg = ( - "BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer2" - ) - assert len(routes) == 4, assertmsg - assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer2" - for route in routes: - assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time - 65 > int(route.split()[3].split(":")[1]) > 55 - ), assertmsg # minutes of reuse time - - # end test_bgp_dampening_profile_group_over_global - - -def test_bgp_dampening_profile_peer_over_global(): - "Test of BGP route-flap dampening profile preferences: peer over global" - - # This test verifies that the dampening profile of a peer takes precedence - # over the global dampening profile by flapping the routes of the peer until - # dampened and comparing the reuse times to the one specified in the - # dampening configuration. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info( - "Starting test of BGP route-flap dampening profile preferences: peer over global" - ) - - # Flapping routes on ExaBGP peer peer3 - logger.info( - "Flapping routes on ExaBGP peer peer3 with route-flap dampening enabled" - ) - for _ in range(1, 5): - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer3.in", "w") - with pipe: - pipe.write( - "withdraw route 192.168.5{}.0/24 next-hop 192.168.101.5\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - sleep(1) # Give the BGP session on router r1 time to process routes - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer3.in", "w") - with pipe: - pipe.write( - "announce route 192.168.5{}.0/24 next-hop 192.168.101.5\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Check damped paths on r1 for routes of peer3 witn peer profile - logger.info( - "Checking if router r1 used the correct dampening profile on routes flapped by ExaBGP peer peer3" - ) - sleep(5) # wait 5 seconds for paths to shop up in damp list - vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"') - routes = re.findall(r"\*d 192\.168\.5\d\.0\/24.*", vtyout) - assertmsg = ( - "BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer3" - ) - assert len(routes) == 4, assertmsg - assertmsg = "BGP session on router r1 used wrong dampening profile for a route flapped by ExaBGP peer peer3" - for route in routes: - assert (int(route.split()[3].split(":")[0]) == 0) and ( # hours of reuse time - 35 > int(route.split()[3].split(":")[1]) > 25 - ), assertmsg # minutes of reuse time - - # end test_bgp_dampening_profile_peer_over_global - - -def test_bgp_dampening_profile_global(): - "Test of BGP route-flap dampening global profile" - - # This test verifies the application of the global dampening profile by - # flapping the routes of a peer until dampened and comparing the reuse times - # to the one specified in the dampening configuration. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting test of BGP route-flap dampening global profile") - - # Flapping routes on ExaBGP peer peer4 - logger.info( - "Flapping routes on ExaBGP peer peer4 with route-flap dampening enabled" - ) - for _ in range(1, 5): - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer4.in", "w") - with pipe: - pipe.write( - "withdraw route 192.168.6{}.0/24 next-hop 192.168.101.6\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - sleep(1) # Give the BGP session on router r1 time to process routes - for prefix_iter in range(1, 5): - pipe = open("/run/exabgp_peer4.in", "w") - with pipe: - pipe.write( - "announce route 192.168.6{}.0/24 next-hop 192.168.101.6\n".format( - prefix_iter - ) - ) - pipe.close() - sleep(0.1) # ExaBGP API command processing delay - - # Check damped paths on r1 for routes of peer4 witn global profile - logger.info( - "Checking if router r1 used the global dampening profile on routes flapped by ExaBGP peer peer4" - ) - sleep(5) # wait 5 seconds for paths to shop up in damp list - vtyout = r_1.cmd('vtysh -c "show ip bgp dampening dampened-paths"') - routes = re.findall(r"\*d 192\.168\.6\d\.0\/24.*", vtyout) - assertmsg = ( - "BGP session on router r1 did not dampen routes flapped by ExaBGP peer peer4" - ) - assert len(routes) == 4, assertmsg - assertmsg = "BGP session on router r1 did not use the global dampening profile for a route flapped by ExaBGP peer peer4" - for route in routes: - assert (int(route.split()[3].split(":")[0]) == 1) and ( # hours of reuse time - 35 > int(route.split()[3].split(":")[1]) > 25 - ), assertmsg # minutes of reuse time - - # end test_bgp_dampening_profile_global - - -def test_bgp_dampening_withdaw(): - "Test BGP route-flap dampening route withdraw" - - # This test verifies that the withrawl of dampened routes from the RIB of - # router r1 was propagated to router r2. - - tgen = get_topogen() - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting test of BGP route-flap dampening route withdraw") - - # Check if routes dampened on router r1 have been withdrawn from the RIB on - # router r2 - logger.info( - "Checking if routes dampened on router r1 have been withdrawn of RIB on router r2" - ) - reffile = os.path.join(CWD, "r2/bgp_damp_withdrawn.json") - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, tgen.gears["r2"], "show ip bgp json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=5, wait=1) - assertmsg = "BGP session on router r2 did not receive withdraw of routes dampened on router r1" - assert res is None, assertmsg - - # end test_bgp_dampening_withdaw - - -def test_bgp_dampening_cleanup(): - "BGP route-flap dampening test cleanup" - - # This test cleans up after other tests associated with route-flap dampening - # by disabling all dampening configurations, removing added peers and - # peer-groups from the configuration on router r1, and shutting down ExaBGP - # peers peer1, peer2 and peer3. - - tgen = get_topogen() - r_1 = tgen.net["r1"] - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - logger.info("Starting BGP route-flap dampening test cleanup") - - # Disable all dampening configurations - logger.info("Disabling all dampening configurations") - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no bgp dampening"' - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor group1 dampening"' - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor 192.168.101.3 dampening"' - ) - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "address-family ipv4 unicast" -c "no neighbor 192.168.101.5 dampening"' - ) - - # Remove ExaBGP peers from configuration of router r1 - logger.info("Removing ExaBGP peers from configuration of router r1") - for router_num in range(3, 7): - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor 192.168.101.{}"'.format( - router_num - ) - ) - - # Remove peer-group group1 from configuration of router r1 - logger.info("Removing peer-group group1 peers from configuration of router r1") - r_1.cmd( - 'vtysh -c "conf t" -c "router bgp 65000" -c "no neighbor group1 peer-group"' - ) - - # Stop ExaBGP peers and remove associated named pipes - logger.info("Stopping ExaBGP peers and removing associated named pipes") - for peer_num in range(1, 5): - logger.info("Terminating ExaBGP on peer peer{}".format(peer_num)) - peer = tgen.gears["peer{}".format(peer_num)] - logger.info("Removing named pipe of ExaBGP peer peer{}".format(peer_num)) - fifo_in = "/var/run/exabgp_peer{}.in".format(peer_num) - peer.stop() - if os.path.exists(fifo_in): - os.remove(fifo_in) - - # end test_bgp_dampening_cleanup - - -def test_bgp_dampening_aftermath(): - "BGP route-flap dampening aftermath test" - - # This test verifies routers r1 and r2 not being affected by the route-flap - # dampening test series. - - tgen = get_topogen() - - # Skip if previous fatal error condition is raised - if tgen.routers_have_failure(): - pytest.skip(tgen.errors) - - # Check BGP Summary on routers r1 and r2 - for rtr_num in [1, 2]: - logger.info( - "Checking if BGP router on r{} remains unaffected by route-flap dampening tests".format( - rtr_num - ) - ) - router = tgen.gears["r{}".format(rtr_num)] - reffile = os.path.join(CWD, "r{}/show_bgp.json".format(rtr_num)) - expected = json.loads(open(reffile).read()) - test_func = functools.partial( - topotest.router_json_cmp, router, "show ip bgp json", expected - ) - _, res = topotest.run_and_expect(test_func, None, count=10, wait=2) - assertmsg = "BGP routes on router r{} are wrong after route-flap dampening tests".format( - rtr_num - ) - assert res is None, assertmsg - - # end test_bgp_dampening_aftermath - - if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args))