diff options
39 files changed, 305 insertions, 1682 deletions
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 7ba0472d72..f46d416c3c 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; - - 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; -} +/* Global variable to access damping configuration */ +static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX]; -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,38 +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; -/* Delete BGP dampening information from reuse list. */ -static void bgp_reuse_list_delete(struct bgp_damp_info *bdi) -{ - bgp_damp_info_unclaim(bdi); -} + index = bdi->index = bgp_reuse_index(bdi->penalty, bdc); -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); + 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; } -static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi, - struct bgp_damp_config *bdc) +/* 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_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. */ @@ -222,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; @@ -278,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; } @@ -309,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; @@ -337,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. */ @@ -376,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; @@ -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; @@ -421,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 @@ -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); + 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, @@ -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,38 +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_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; - 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, &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; @@ -585,81 +428,96 @@ void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc, 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. - */ -int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi) +/* Clean all the bgp_damp_info stored in reuse_list. */ +void bgp_damp_info_clean(afi_t afi, safi_t safi) { - struct bgp_damp_config *bdc; + unsigned int i; + struct bgp_damp_info *bdi, *next; + struct bgp_damp_config *bdc = &damp[afi][safi]; - bdc = &bgp->damp[afi][safi]; - if (!bdc) - return 0; + 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 = &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); - UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING); + /* 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 @@ -711,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; @@ -745,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", @@ -757,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, @@ -774,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; @@ -796,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", @@ -825,8 +678,8 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi, uint8_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; @@ -865,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 62b49dcb91..604706300b 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 *bdi, - 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 *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_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, uint8_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_fsm.c b/bgpd/bgp_fsm.c index a242510566..c8aabec504 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1378,6 +1378,9 @@ int bgp_stop(struct peer *peer) peer->fd = -1; } + /* Reset capabilities. */ + peer->cap = 0; + FOREACH_AFI_SAFI (afi, safi) { /* Reset all negotiated variables */ peer->afc_nego[afi][safi] = 0; diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index fc508496cc..1a35addac5 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 4080248038..23e1d082a4 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_open.c b/bgpd/bgp_open.c index 94d905127d..113017559e 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1216,7 +1216,8 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability) /* Extended Message Support */ peer->max_packet_size = - CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV) + (CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV) + && CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV)) ? BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE : BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8bbdb05248..3490a4fa40 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -216,6 +216,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) { @@ -3378,16 +3381,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) { @@ -3856,7 +3857,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, && (overlay_index_equal( afi, pi, evpn == NULL ? NULL : &evpn->gw_ip))) { - 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)) { @@ -3950,11 +3952,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); } @@ -4077,7 +4079,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); @@ -10207,7 +10209,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]) @@ -14359,7 +14361,6 @@ 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, - &bgp->damp[afi][safi], 1, afi, safi); pi = pi_temp; } else @@ -14380,24 +14381,8 @@ 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, - &bgp->damp[afi][safi], 1, afi, safi); pi = pi_temp; } else @@ -14420,9 +14405,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 824b326e90..ea0e0a5823 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7948,93 +7948,6 @@ DEFPY( return CMD_SUCCESS; } -DEFPY(neighbor_damp, - neighbor_damp_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [(1-45)$half [(1-20000)$reuse (1-20000)$suppress (1-255)$max]]", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable neighbor route-flap dampening\n" - "Half-life time for the penalty\n" - "Value to start reusing a route\n" - "Value to start suppressing a route\n" - "Maximum duration to suppress a stable route\n") -{ - struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); - - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - if (!half) - half = DEFAULT_HALF_LIFE; - if (!reuse) { - reuse = DEFAULT_REUSE; - suppress = DEFAULT_SUPPRESS; - max = half * 4; - } - if (suppress < reuse) { - vty_out(vty, - "Suppress value cannot be less than reuse value\n"); - return CMD_WARNING_CONFIG_FAILED; - } - bgp_peer_damp_enable(peer, bgp_node_afi(vty), bgp_node_safi(vty), - half * 60, reuse, suppress, max * 60); - return CMD_SUCCESS; -} - -DEFPY(no_neighbor_damp, - no_neighbor_damp_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [HALF [REUSE SUPPRESS MAX]]", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Enable neighbor route-flap dampening\n" - "Half-life time for the penalty\n" - "Value to start reusing a route\n" - "Value to start suppressing a route\n" - "Maximum duration to suppress a stable route\n") -{ - struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); - - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - bgp_peer_damp_disable(peer, bgp_node_afi(vty), bgp_node_safi(vty)); - return CMD_SUCCESS; -} - -DEFPY (show_ip_bgp_neighbor_damp_param, - show_ip_bgp_neighbor_damp_param_cmd, - "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD>$neighbor dampening parameters [json]$json", - SHOW_STR - IP_STR - BGP_STR - BGP_AFI_HELP_STR - "Address Family modifier\n" - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Neighbor route-flap dampening information\n" - "Display detail of configured dampening parameters\n" - JSON_STR) -{ - bool use_json = false; - int idx = 0; - afi_t afi = AFI_IP; - safi_t safi = SAFI_UNICAST; - struct peer *peer; - - if (argv_find(argv, argc, "ip", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv4", &idx)) - afi = AFI_IP; - if (argv_find(argv, argc, "ipv6", &idx)) - afi = AFI_IP6; - peer = peer_and_group_lookup_vty(vty, neighbor); - if (!peer) - return CMD_WARNING; - if (json) - use_json = true; - bgp_show_peer_dampening_parameters(vty, peer, afi, safi, use_json); - return CMD_SUCCESS; -} - static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, struct ecommunity **list, bool is_rt6) { @@ -16409,9 +16322,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. */ @@ -16464,7 +16374,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); @@ -18247,23 +18157,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/bgp_zebra.c b/bgpd/bgp_zebra.c index 00d91c2b27..3f8dc82a44 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1416,8 +1416,9 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, struct aspath *aspath = info->attr->aspath; SET_FLAG(api.message, ZAPI_MESSAGE_OPAQUE); - api.opaque.length = strlen(aspath->str) + 1; - memcpy(api.opaque.data, aspath->str, api.opaque.length); + strlcpy((char *)api.opaque.data, aspath->str, + sizeof(api.opaque.data)); + api.opaque.length = strlen((char *)api.opaque.data) + 1; } if (allow_recursion) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d3f3078110..e816b98e27 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1440,7 +1440,6 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src) /* peer flags apply */ peer_dst->flags = peer_src->flags; - peer_dst->cap = peer_src->cap; peer_dst->peer_gr_present_state = peer_src->peer_gr_present_state; peer_dst->peer_gr_new_status_flag = peer_src->peer_gr_new_status_flag; @@ -2405,14 +2404,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) { @@ -3591,11 +3582,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 4a17b72b7f..ab487f3f4b 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -43,7 +43,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" @@ -715,9 +714,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]; - QOBJ_FIELDS; }; DECLARE_QOBJ_TYPE(bgp); @@ -1271,9 +1267,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 @@ -1311,8 +1304,6 @@ struct peer { #define PEER_FLAG_SEND_LARGE_COMMUNITY (1U << 26) /* Send large Communities */ #define PEER_FLAG_MAX_PREFIX_OUT (1U << 27) /* outgoing maximum prefix */ #define PEER_FLAG_MAX_PREFIX_FORCE (1U << 28) /* maximum-prefix <num> force */ -#define PEER_FLAG_CONFIG_DAMPENING (1U << 29) /* route flap dampening */ - enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX]; diff --git a/doc/developer/conf.py b/doc/developer/conf.py index 20265f4aad..8f282c0790 100644 --- a/doc/developer/conf.py +++ b/doc/developer/conf.py @@ -395,8 +395,11 @@ def setup(app): # printfrr extensions app.add_object_type("frrfmt", "frrfmt", parse_node=parse_frrfmt) - # css overrides for HTML theme - app.add_stylesheet("overrides.css") + if "add_css_file" in dir(app): + app.add_css_file("overrides.css") + else: + app.add_stylesheet("overrides.css") + # load Pygments lexer for FRR config syntax # # NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 0000000000..debc7f1889 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1 @@ +sphinx==4.0.2 diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index f6aa5d1ca0..759fa4af73 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -499,54 +499,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 @@ -3312,17 +3286,17 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. It helps to identify which prefixes were installed at some point. Here is an example of how to check what prefixes were installed starting - with an arbitrary version:: + with an arbitrary version: - .. code-block:: frr +.. code-block:: shell - ~# vtysh -c 'show bgp ipv4 unicast json' | jq '.tableVersion' - 9 - ~# vtysh -c 'show ip bgp version 9 json' | jq -r '.routes | keys[]' - 192.168.3.0/24 - ~# vtysh -c 'show ip bgp version 8 json' | jq -r '.routes | keys[]' - 192.168.2.0/24 - 192.168.3.0/24 + # vtysh -c 'show bgp ipv4 unicast json' | jq '.tableVersion' + 9 + # vtysh -c 'show ip bgp version 9 json' | jq -r '.routes | keys[]' + 192.168.3.0/24 + # vtysh -c 'show ip bgp version 8 json' | jq -r '.routes | keys[]' + 192.168.2.0/24 + 192.168.3.0/24 .. clicmd:: show bgp [afi] [safi] statistics diff --git a/doc/user/conf.py b/doc/user/conf.py index e0aec40443..6db58b07c3 100644 --- a/doc/user/conf.py +++ b/doc/user/conf.py @@ -386,16 +386,17 @@ def setup(app): # node later on app.add_object_type("clicmd", "clicmd", indextemplate="pair: %s; configuration command") - # css overrides for HTML theme - # Note sphinx version differences - sver = vparse(sphinx.__version__) - - if sver < vparse("1.8.0"): - app.add_stylesheet("overrides.css") - app.add_javascript("overrides.js") + # I dont care how stupid this is + if "add_js_file" in dir(app): + app.add_js_file("overrides.js") else: + app.add_javascript("overrides.js") + + if "add_css_file" in dir(app): app.add_css_file("overrides.css") - app.add_js_file("overrides.js") + else: + app.add_stylesheet("overrides.css") + # load Pygments lexer for FRR config syntax # diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 817af33ff2..7d5f516be0 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -70,6 +70,19 @@ OSPF6 router Use this command to control the maximum number of parallel routes that OSPFv3 can support. The default is 64. +.. clicmd:: area A.B.C.D range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>] + +.. clicmd:: area (0-4294967295) range X:X::X:X/M [<advertise|not-advertise|cost (0-16777215)>] + + Summarize a group of internal subnets into a single Inter-Area-Prefix LSA. + This command can only be used at the area boundary (ABR router). + + By default, the metric of the summary route is calculated as the highest + metric among the summarized routes. The `cost` option, however, can be used + to set an explicit metric. + + The `not-advertise` option, when present, prevents the summary route from + being advertised, effectively filtering the summarized routes. .. _ospf6-area: diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index c1d279388e..4dbbf84885 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -784,10 +784,11 @@ IPv6 example for OSPFv3. .. note:: - For both IPv4 and IPv6, the IP address has to exist at the point the - route-map is created. Be wary of race conditions if the interface is - not created at startup. On Debian, FRR might start before ifupdown - completes. Consider a reboot test. + For both IPv4 and IPv6, the IP address has to exist on some interface when + the route is getting installed into the system. Otherwise, kernel rejects + the route. To solve the problem of disappearing IPv6 addresses when the + interface goes down, use ``net.ipv6.conf.all.keep_addr_on_down`` + :ref:`sysctl option <zebra-sysctl>`. .. clicmd:: zebra route-map delay-timer (0-600) @@ -1103,6 +1104,8 @@ For protocols requiring an IPv6 router-id, the following commands are available: Display the user configured IPv6 router-id. +.. _zebra-sysctl: + Expected sysctl settings ======================== diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 963fa4d995..a1c4904733 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -1210,7 +1210,7 @@ static int interface_config_write(struct vty *vty) vty_out(vty, "dynamic"); else vty_out(vty, "%pSU", &nhs->proto_addr); - vty_out(vty, "nbma %s\n", nhs->nbma_fqdn); + vty_out(vty, " nbma %s\n", nhs->nbma_fqdn); } list_for_each_entry(mcast, &ad->mcastlist_head, diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index c025dcf5bf..33cd7d8198 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -496,7 +496,7 @@ DEFUN (area_range, struct ospf6_area *oa; struct prefix prefix; struct ospf6_route *range; - uint32_t cost = OSPF_AREA_RANGE_COST_UNSPEC; + uint32_t cost; VTY_DECLVAR_CONTEXT(ospf6, ospf6); @@ -518,16 +518,15 @@ DEFUN (area_range, range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; } + /* default settings */ + cost = OSPF_AREA_RANGE_COST_UNSPEC; + UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); + if (argc > idx_type) { - if (strmatch(argv[idx_type]->text, "not-advertise")) { + if (strmatch(argv[idx_type]->text, "not-advertise")) SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); - } else if (strmatch(argv[idx_type]->text, "advertise")) { - UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); - cost = range->path.u.cost_config; - } else { + else if (strmatch(argv[idx_type]->text, "cost")) cost = strtoul(argv[5]->arg, NULL, 10); - UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE); - } } range->path.u.cost_config = cost; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index da9c0183be..7f772fdb88 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -375,10 +375,27 @@ static void ospf_passive_interface_default_update(struct ospf *ospf, ospf_if_set_multicast(oi); } -static void ospf_passive_interface_update(struct interface *ifp) +static void ospf_passive_interface_update(struct interface *ifp, + struct ospf_if_params *params, + struct in_addr addr, uint8_t newval) { struct route_node *rn; + if (OSPF_IF_PARAM_CONFIGURED(params, passive_interface)) { + if (params->passive_interface == newval) + return; + + params->passive_interface = newval; + UNSET_IF_PARAM(params, passive_interface); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + params->passive_interface = newval; + SET_IF_PARAM(params, passive_interface); + } + /* * XXX We should call ospf_if_set_multicast on exactly those * interfaces for which the passive property changed. It is too much @@ -457,10 +474,7 @@ DEFUN_HIDDEN (ospf_passive_interface_addr, params = IF_DEF_PARAMS(ifp); } - params->passive_interface = OSPF_IF_PASSIVE; - SET_IF_PARAM(params, passive_interface); - - ospf_passive_interface_update(ifp); + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_PASSIVE); return CMD_SUCCESS; } @@ -521,14 +535,7 @@ DEFUN_HIDDEN (no_ospf_passive_interface, params = IF_DEF_PARAMS(ifp); } - params->passive_interface = OSPF_IF_ACTIVE; - UNSET_IF_PARAM(params, passive_interface); - if (params != IF_DEF_PARAMS(ifp)) { - ospf_free_if_params(ifp, addr); - ospf_if_update_params(ifp, addr); - } - - ospf_passive_interface_update(ifp); + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_ACTIVE); return CMD_SUCCESS; } @@ -9082,7 +9089,7 @@ DEFUN (ip_ospf_passive, { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_ipv4 = 3; - struct in_addr addr; + struct in_addr addr = {.s_addr = INADDR_ANY}; struct ospf_if_params *params; int ret; @@ -9099,10 +9106,7 @@ DEFUN (ip_ospf_passive, params = IF_DEF_PARAMS(ifp); } - params->passive_interface = OSPF_IF_PASSIVE; - SET_IF_PARAM(params, passive_interface); - - ospf_passive_interface_update(ifp); + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_PASSIVE); return CMD_SUCCESS; } @@ -9118,7 +9122,7 @@ DEFUN (no_ip_ospf_passive, { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_ipv4 = 4; - struct in_addr addr; + struct in_addr addr = {.s_addr = INADDR_ANY}; struct ospf_if_params *params; int ret; @@ -9136,14 +9140,7 @@ DEFUN (no_ip_ospf_passive, params = IF_DEF_PARAMS(ifp); } - params->passive_interface = OSPF_IF_ACTIVE; - UNSET_IF_PARAM(params, passive_interface); - if (params != IF_DEF_PARAMS(ifp)) { - ospf_free_if_params(ifp, addr); - ospf_if_update_params(ifp, addr); - } - - ospf_passive_interface_update(ifp); + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_ACTIVE); return CMD_SUCCESS; } @@ -11932,7 +11929,11 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf) if (OSPF_IF_PARAM_CONFIGURED(params, passive_interface)) { - vty_out(vty, " ip ospf passive"); + vty_out(vty, " %sip ospf passive", + params->passive_interface + == OSPF_IF_ACTIVE + ? "no " + : ""); if (params != IF_DEF_PARAMS(ifp) && rn) vty_out(vty, " %pI4", &rn->p.u.prefix4); vty_out(vty, "\n"); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 1bf3a619bf..3b00e779cf 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1232,6 +1232,16 @@ int pim_ifchannel_local_membership_add(struct interface *ifp, __FILE__, __func__, child->sg_str, ifp->name, up->sg_str); + if (!child->rpf.source_nexthop.interface) { + /* when iif unknown, do not inherit */ + if (PIM_DEBUG_EVENTS) + zlog_debug( + "Skipped (S,G)=%s(%s) from %s: no iif", + child->sg_str, ifp->name, + up->sg_str); + continue; + } + ch = pim_ifchannel_find(ifp, &child->sg); if (pim_upstream_evaluate_join_desired_interface( child, ch, starch)) { diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index a31fec036f..d706fd8693 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -139,11 +139,12 @@ void pim_rp_init(struct pim_instance *pim) void pim_rp_free(struct pim_instance *pim) { - if (pim->rp_list) - list_delete(&pim->rp_list); if (pim->rp_table) route_table_finish(pim->rp_table); pim->rp_table = NULL; + + if (pim->rp_list) + list_delete(&pim->rp_list); } /* diff --git a/ripd/ripd.c b/ripd/ripd.c index 7d940efd9c..3adbfeb003 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -920,9 +920,11 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from, if (key == NULL || key->string == NULL) return 0; - strlcpy(auth_str, key->string, sizeof(auth_str)); + memcpy(auth_str, key->string, + MIN(sizeof(auth_str), strlen(key->string))); } else if (ri->auth_str) - strlcpy(auth_str, ri->auth_str, sizeof(auth_str)); + memcpy(auth_str, ri->auth_str, + MIN(sizeof(auth_str), strlen(ri->auth_str))); if (auth_str[0] == 0) return 0; @@ -965,9 +967,11 @@ static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key, memset(auth_str, 0, len); if (key && key->string) - strlcpy(auth_str, key->string, len); + memcpy(auth_str, key->string, + MIN((size_t)len, strlen(key->string))); else if (ri->auth_str) - strlcpy(auth_str, ri->auth_str, len); + memcpy(auth_str, ri->auth_str, + MIN((size_t)len, strlen(ri->auth_str))); return; } 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)) diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 07a8288605..855e19dc45 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -1002,7 +1002,6 @@ static int zfpm_build_route_updates(void) data_len = zfpm_encode_route(dest, re, (char *)data, buf_end - data, &msg_type); - assert(data_len); if (data_len) { hdr->msg_type = msg_type; msg_len = fpm_data_len_to_msg_len(data_len); @@ -1013,6 +1012,9 @@ static int zfpm_build_route_updates(void) zfpm_g->stats.route_adds++; else zfpm_g->stats.route_dels++; + } else { + zlog_err("%s: Encoding Prefix: %pRN No valid nexthops", + __func__, dest->rnode); } } diff --git a/zebra/zebra_routemap_nb_config.c b/zebra/zebra_routemap_nb_config.c index 8f5660610f..5bcfb720e1 100644 --- a/zebra/zebra_routemap_nb_config.c +++ b/zebra/zebra_routemap_nb_config.c @@ -247,9 +247,7 @@ lib_route_map_entry_set_action_rmap_set_action_ipv4_src_address_modify( struct nb_cb_modify_args *args) { struct routemap_hook_context *rhc; - struct interface *pif = NULL; const char *source; - struct vrf *vrf; struct prefix p; int rv; @@ -262,18 +260,6 @@ lib_route_map_entry_set_action_rmap_set_action_ipv4_src_address_modify( yang_dnode_get_string(args->dnode, NULL)); return NB_ERR_VALIDATION; } - - RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { - pif = if_lookup_exact_address(&p.u.prefix4, AF_INET, - vrf->vrf_id); - if (pif != NULL) - break; - } - if (pif == NULL) { - zlog_warn("%s: is not a local address: %s", __func__, - yang_dnode_get_string(args->dnode, NULL)); - return NB_ERR_VALIDATION; - } return NB_OK; case NB_EV_PREPARE: case NB_EV_ABORT: @@ -325,9 +311,7 @@ lib_route_map_entry_set_action_rmap_set_action_ipv6_src_address_modify( struct nb_cb_modify_args *args) { struct routemap_hook_context *rhc; - struct interface *pif = NULL; const char *source; - struct vrf *vrf; struct prefix p; int rv; @@ -340,18 +324,6 @@ lib_route_map_entry_set_action_rmap_set_action_ipv6_src_address_modify( yang_dnode_get_string(args->dnode, NULL)); return NB_ERR_VALIDATION; } - - RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id) { - pif = if_lookup_exact_address(&p.u.prefix6, AF_INET6, - vrf->vrf_id); - if (pif != NULL) - break; - } - if (pif == NULL) { - zlog_warn("%s: is not a local address: %s", __func__, - yang_dnode_get_string(args->dnode, NULL)); - return NB_ERR_VALIDATION; - } return NB_OK; case NB_EV_PREPARE: case NB_EV_ABORT: |
